Skip to content

GenericScope.setSerializationId can cause serialization issues #93

@rwinch

Description

@rwinch

GenericScope.setSerializationId can cause serialization issues as illustrated in spring-projects/spring-session#395

The failure happens when trying to serialize Session Scoped beans because DefaultListableBeanFactory.serializationId has a different value from when the serialization takes place and when the deserialization takes place.

In Spring Cloud, the GenericScope.setSerializationId sets the serialization id. This means both RefreshScope and ThreadScope (which inherit from GenericScope) are impacted by this.

The default value is a UUID calculated from the bytes of the Spring Bean names. Unfortunately the calculation of the resulting id does not appear to be constant. When the same application is restarted, the UUID is still different than the previous id.

Ultimately, this can cause the following stacktrace:

2016-02-26 14:51:34.092 ERROR 51427 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.lang.IllegalStateException: Cannot deserialize BeanFactory with id application:9000: no factory registered for this id
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:41) ~[spring-data-redis-1.6.2.RELEASE.jar:1.6.2.RELEASE]
    at org.springframework.data.redis.core.AbstractOperations.deserializeHashValue(AbstractOperations.java:316) ~[spring-data-redis-1.6.2.RELEASE.jar:1.6.2.RELEASE]
    at org.springframework.data.redis.core.AbstractOperations.deserializeHashMap(AbstractOperations.java:277) ~[spring-data-redis-1.6.2.RELEASE.jar:1.6.2.RELEASE]
    at org.springframework.data.redis.core.DefaultHashOperations.entries(DefaultHashOperations.java:227) ~[spring-data-redis-1.6.2.RELEASE.jar:1.6.2.RELEASE]
    at org.springframework.data.redis.core.DefaultBoundHashOperations.entries(DefaultBoundHashOperations.java:101) ~[spring-data-redis-1.6.2.RELEASE.jar:1.6.2.RELEASE]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository.getSession(RedisOperationsSessionRepository.java:233) ~[spring-session-1.0.2.RELEASE.jar:na]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository.getSession(RedisOperationsSessionRepository.java:220) ~[spring-session-1.0.2.RELEASE.jar:na]
    at org.springframework.session.data.redis.RedisOperationsSessionRepository.getSession(RedisOperationsSessionRepository.java:141) ~[spring-session-1.0.2.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.getSession(SessionRepositoryFilter.java:276) ~[spring-session-1.0.2.RELEASE.jar:na]
    at org.springframework.web.context.request.ServletRequestAttributes.updateAccessedSessionAttributes(ServletRequestAttributes.java:255) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.context.request.AbstractRequestAttributes.requestCompleted(AbstractRequestAttributes.java:48) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:106) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:125) ~[spring-session-1.0.2.RELEASE.jar:na]
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:65) ~[spring-session-1.0.2.RELEASE.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103) ~[spring-boot-actuator-1.3.2.RELEASE.jar:1.3.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) ~[tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_65]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_65]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.lang.Thread.run(Thread.java:745) [na:1.7.0_65]
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.lang.IllegalStateException: Cannot deserialize BeanFactory with id application:9000: no factory registered for this id
    at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:78) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:36) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:39) ~[spring-data-redis-1.6.2.RELEASE.jar:1.6.2.RELEASE]
    ... 49 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot deserialize BeanFactory with id application:9000: no factory registered for this id
    at org.springframework.beans.factory.support.DefaultListableBeanFactory$SerializedBeanFactoryReference.readResolve(DefaultListableBeanFactory.java:1428) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_65]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_65]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_65]
    at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_65]
    at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1104) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1807) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1706) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1344) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:500) ~[na:1.7.0_65]
    at org.springframework.aop.framework.AdvisedSupport.readObject(AdvisedSupport.java:557) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_65]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_65]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_65]
    at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_65]
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350) ~[na:1.7.0_65]
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370) ~[na:1.7.0_65]
    at org.springframework.core.serializer.DefaultDeserializer.deserialize(DefaultDeserializer.java:70) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.core.serializer.support.DeserializingConverter.convert(DeserializingConverter.java:73) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ... 51 common frames omitted

Demo

You can find an example for reproducing this in rwinch/tut-spring-security-and-angular-js. Use the following instructions:

  • Ensure all cookies for localhost are cleared out
  • Start up Redis instance
  • Start oauth2/resource oauth2/ui and oauth2/authserver/
  • open http://localhost:8080/
  • Authenticated with user / password

Use the following branches

Workaround

This can be worked around by creating a RefreshScope bean definition. For example:

@Bean
public static RefreshScope refreshScope() {
    RefreshScope refresh = new RefreshScope();
    refresh.setId("application:1");
    return refresh;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions