-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Description
In our app we use Spring Integration, which relies to some degree on java serialization. There in one spring integration endpoint which calls some rest api using standard RestTemplate. In case of 500 error from remote service the HttpServerErrorException is thrown. This exception is serialized later as it flows through Spring Integration channels.
Now this HttpServerErrorException subclasses RestClientResponseException which contains field bodyConvertFunction, which is by default set to DefaultResponseErrorHandler (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/DefaultResponseErrorHandler.html) which is not serializable.
As a result such dependency on this DefaultRespoinseErrorHandler, the instances of HttpServerErrorException are not serializable and causes this Spring Integration app to fail. Anyway it is not related to Spring Integration as the Exception should be serializable, meaning that all the fields should be serializable as well.
Interesting thing, that is seems that the linter was trying to highligt this issue, but it was surppressed in sources of : https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/client/RestClientResponseException.java
public class RestClientResponseException extends RestClientException {
private static final long serialVersionUID = -8803556342728481792L;
(...)
@Nullable
@SuppressWarnings("serial")
private Function<ResolvableType, ?> bodyConvertFunction;
}
Found in spring boot 3..0.2 (spring 6.0.4), but looking at source in github the issue seems to be there in newer versions
Interesting part of the exception message:
Caused by: java.io.NotSerializableException: org.springframework.web.client.DefaultResponseErrorHandler$$Lambda$4073/0x0000000801e6b7e0 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1197) ~[?:?] at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1582) ~[?:?] at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1539) ~[?:?] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1448) ~[?:?] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1191) ~[?:?] at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1582) ~[?:?] at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:447) ~[?:?] at java.lang.Throwable.writeObject(Throwable.java:1014) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?] at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1074) ~[?:?] at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1526) ~[?:?] at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1448) ~[?:?] at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1191) ~[?:?] at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1582) ~[?:?] at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:447) ~[?:?] at java.lang.Throwable.writeObject(Throwable.java:1014) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]