-
Notifications
You must be signed in to change notification settings - Fork 41.2k
ContextIdApplicationContextInitializer prevents serialization of Session Scope beans on different ports #5265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The context id defaults to something basically sensible IMO (and please don't change it), so the problem with Spring Session is that the serialization id defaults to the same as the context id (whereas in this case it should be different). The fact that people shouldn't really be putting scoped proxies in session scope is also relevant, but the fix for that isn't going to be in Boot. By the way, the test that Rob linked to above passes for me (after I allocate |
@dsyer Thanks for your response.
I disagree that this default makes sense. If I run the exact same application on multiple ports (to scale), then serialization will not work. This is very stark contrast to what I would expect since serialization is typically quite necessary across an application running on multiple ports.
That may be true (but see next paragraph), but it is a prevalent problem in the framework and this issue is blocking quite a few users until the rest of the framework can be fixed. I'd like to point out that the underlying issue is not session serialization (so even if we remove the proxies it is not fixing the underlying problem). The real issue is serialization of an ApplicationContext is not consistent. There may be other reasons for serializing the ApplicationContext. I'd be interested to know the reason that Boot (and Cloud) set the |
Yes, but that's not because the context id is different, it's because the serialization id is different. I like the context id the way it is, but please feel free to suggest a change to the serialization id. Without Spring Boot, by the way, both values are random, so the failure is even more noticeable.
Yes it is. You don't need to serialize a
Spring Boot sets it so that you get some semblance of persistence - the same app running in 2 different processes sequentially has the same ID. This actually helps the serialization issue (assuming that you don't scale up on the same host, which you wouldn't in production anyway). It's used in Spring Cloud Bus to address messages to individual application instances. |
It checked and this statement is wrong for a web app (the id is defaulted in |
I guess we need to call |
It's not so urgent for the original use case now that spring (4.3) is more liberal. But maybe we should set it, and if so, then copying spring cloud (context) makes sense. It tries to do it in a way that will work for scaled up apps locally and in Cloud Foundry. The only issue is that spring boot doesn't have any special role for |
@dsyer I am working on an application that uses @EnableOAuth2Client annotation to initiate authorization code grant flow and redis for storing session. I have been experiencing the deserialization issue in resource server noted in this thread as well. Workaround suggested by @rwinch helped but as soon as I start using a profile to start the resource application, deserialization error happens because serialization id in DefaultListableBeanFactory now has profile name in it. I ended up setting serialization id as follows in authorization server and resource server. GenericApplicationContext context = (GenericApplicationContext)SpringApplication.run(AuthserverApplication.class, args);
((DefaultListableBeanFactory)context.getBeanFactory()).setSerializationId("customid"); GenericApplicationContext context = (GenericApplicationContext) SpringApplication.run(ResourceApplication.class, args)
((DefaultListableBeanFactory)context.getBeanFactory()).setSerializationId("customid"); This seems to work. I am seeking your feedback to see if you notice any issues with this approach. |
@ghsbhatia Can you try updating to Spring Framework 4.3.0.RELEASE? This should fix your problem due to the changes made as a part of spring-attic/spring-security-oauth#705 |
Is there any update for this issue? I am still getting a form of this in Spring Framework 4.3.2. The workaround from @ghsbhatia worked for me as well. To be more specific, I originally had in my auth server application.yml
And then in my UI server I have the following config
This was enough to run locally just fine, but as soon as there was an active profile (only in a deployed environment for us) I got the error: |
This issue is closed. We don't normally add updates to closed issues (what would be the point?). The UPDATE: cancel that (this issue is not closed). But the |
@collinpeters I doubt that using the same application id in all your apps is going to be a good idea in general. And it's not obvious how refresh scope is relevant to sharing sessions between applications. I think the idea was that you should just back away and not try to "fix" anything with Spring 4.3. Did you try that and it didn't work? Maybe you could share a sample? |
Spring Framework 4.3.x has improved the situation and, given that no one has commented on this issue in the last year, it would appear to no longer be the problem that it was. I'm going to close this for now. We can re-open it if it turns out that it continues to be a problem for people. |
Setting the application context id 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 a Spring Boot application the ContextIdApplicationContextInitializer sets AbstractApplicationContext.id. Then in GenericApplicationContext.refreshBeanFactory() the id is set as the
DefaultListableBeanFactory.serializationId
.Unfortunately Spring Boot's ContextIdApplicationContextInitializer.getApplicationId derives the name of the id from the name of the application and the port the application is running on. This means if you have the same Spring Boot application running on different ports, Session Scoped beans will not work across between the two instances of the application.
Ultimately, this can cause the following stacktrace:
Demo
You can find an example for reproducing this in rwinch/tut-spring-security-and-angular-js. Use the following instructions:
Use the following branches
Workaround
This can be worked around by setting the application name and application index using something like this:
Unfortunately, this impacts other places where the application name and index are used to determine which instance of Spring Boot is being used.
The text was updated successfully, but these errors were encountered: