-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Service references in JSF session objects not restored when using persistent sessions [SPR-2675] #7364
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
Juergen Hoeller commented I frankly have no clue how Tomcat handles this. Does your MyManagedBean class mark the "myService" field as transient? Then this is what I would expect to happen. However, if it's not transient, Tomcat would have to serialize the content of the field, which is the Spring-managed service bean. This is all pretty much standard serialization, and I don't see anything we could do about this in Spring... Juergen |
Oran Epelbaum commented Apparently your're right, the service is declared as transient, which definitely explains this behavior. This seems to me to be a general problem: how to allow the web container to serialize session-state objects, which have references to non-serializable (but typically IoC-controlled) service and DAO objects? I think we may resort to building such a wrapper objects specifically for our services as a fix to this problem, but this is something that's calling for a generic IoC solution: some kind of factory that would create such a wrapper bean on the fly for any object, in the application context. What do you think? |
Juergen Hoeller commented Well, this is the same general issue as with all session-scoped service objects then: If they contain references to shared service objects, those either have to marked as transient (losing those references on serialization) or not considered serializable in the first place (the entire object failing on serialization). This is not really JSF-specific; it's the same with any kind of session object in a Servlet environment. However, a general solution is not apparent here. Spring has no way of interfering in the Servlet container's session persistence process: This means that the Servlet container will simply deserialize those instances and expose them in the reactivated session. We cannot perform dependency injection there, simply because the lifecycle of those objects is beyond Spring's control. So I'm afraid there are only two options:
Juergen |
Oran Epelbaum commented I'll go for option 2 for now, but it feels wrong having to choose between two such options. This looks like a general issue that requires a general solution - web applications would be much better off not being sensitive to serialization / de-serialization of their web-tier beans by the web container. In my comment above I outlined a general solution, and I think it makes sense for this to be part of Spring. When Spring IoC controls a bean, it can certainly wrap it so that it appears to be Serializable. "Forcing" a bean to act as Serializable, while in fact its lifecycle is actually managed by the application context, seems like a cool feature, for avoiding having to choose between those two gloomy options. To explain the idea a bit further, if you have a MyService interface with a void method named method(), I'm suggesting to create a Spring IoC factory that would wrap it with the dynamic equivalent of: class StaticWrapper implements ApplicationContextAware, MyService, Serializable { The only problem i see here is initializing the application context member, since it's not Serializable. Maybe some static global variable is required for storing application context references for this purpose - this is just a sketch. |
Juergen Hoeller commented Thanks for the suggestion - I do see the general idea. You pointed out the most important issue already: Which ApplicationContext do you use for reobtaining the service objects? Spring's philosophy is very much based on avoiding static state wherever possible, hence we refrain from storing ApplicationContexts in static variables unless absolutely necessary. We only do it for two purposes at present: for holding a shared ApplicationContext in an EJB tier, and for holding the ApplicationContext's that exposed for Spring 2.0's Juergen |
Oran Epelbaum commented Well this could be number 3 :-) |
Juergen Hoeller commented This is finally making its way into Spring now! See my comment on #6812... Juergen |
Oran Epelbaum opened SPR-2675 and commented
I am using JSF session-scoped backing beans, initialized by a WebApplicationContext using DelegatingVariableResolver. This all works great until Tomcat is restarted.
When Tomcat is restarted, or the app is re-deployed, Tomcat restores the session from the hard disk. This is a feature new to Tomcat 5.5, called "session persistence". BUT, for some reason the fields of the backing bean that are initialized with Spring are NOT restored, and remain null. As a result, NullPointerExceptions occur in my application after the restore.
As a workaround, we disable this Tomcat feature by adding the following to conf/context.xml:
<Manager pathname="">
<distributable />
</Manager>
I think this might be related to #6951 and #7214, but I'm not sure they relate to the same Tomcat version.
From my faces.xml:
<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
<view-handler>org.apache.myfaces.tomahawk.application.jsp.JspTilesViewHandlerImpl</view-handler>
</application>
<managed-bean>
<managed-bean-name>myManagedBean</managed-bean-name>
<managed-bean-class>com.my.MyManagedBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>myService</property-name>
<value>#{myService}</value>
</managed-property>
</managed-bean>
From my web.xml:
<bean id="myService" class="com.my.MyServiceImpl" />
Note: MyServiceImpl is Serializable.
Affects: 2.0 final
Issue Links:
2 votes, 2 watchers
The text was updated successfully, but these errors were encountered: