Removing JSF beans on session timeout
I am having problems how to properly handle automatic session destruction in JSF. Of course, at this time the session becomes invalid for the container, causing the @PreDestroy methods to be called on the session beans as well.
In the PreDestroy of any session limited to beans, we will unregister some listeners as shown below:
@PreDestroy
public void destroy() {
getWS().removeLanguageChangeListener(this);
}
However, the getWS () method actually tries to get a reference to another scope with a limited session bean, but it fails because it FacesContext.getCurrentInstance()
returns null. The latter appears to be normal JSF behavior, according to Ryan Lübke:
We are correct to the specification here. I'm not sure if it can be assumed that FacesContext will be available in all @PreDestroy cases. Consider session beans. The session may be disconnected due to inactivity. FacesContext is not available at this time.
Okay, but how do you make sure all objects are cleaned up properly? Is it bad practice to remove yourself as a listener in PreDestroy? Or will we only need to do this for the request / view scope given beans, since they live less than the WS session scope (from getWS()
)?
Note that I am getting this behavior on Tomcat7, but I expect this problem to occur on every container.
source to share
I think the session beans are cleaned up on a dedicated thread in the servlet container and thus outside the FacesContext (which is associated with the JSF request). You can use HttpSessionListener
it to overcome problems and clean up session resources. Something like:
@WebListener
public class LifetimeHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(final HttpSessionEvent e) {
// create some instance here and save it in HttpSession map
HttpSession session = e.getSession();
session.setAttribute("some_key", someInstance);
// or elsewhere in JSF context:
// FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("some_key", someInstance);
}
@Override
public void sessionDestroyed(final HttpSessionEvent e) {
// get resources and cleanup them here
HttpSession session = e.getSession();
Object someInstance = session.getAttribute("some_key");
}
}
Hope this can be helpful for you.
source to share