Say I have a running Java based web application with 0 or more valid HttpSession objects associated with it. I want to access the current list of valid HttpSession objects. I thought I could implement the HttpSessionListener and use it to add to the list the session identifier values โโthat are stored in the attribute of the application area, but then I am on the hook to update the list since the sessions are invalid and who knows what else.
Before I start baking my own solution, I thought I should ask a question:
Does the servlet API provide some ways to access a complete list of invalid session objects?
I use Tomcat 6.x as a container for web applications and the MyFaces 1.2.x library (JSF).
Decision
I followed an approach similar to what BalusC discussed on these existing issues:
- How easy is it to implement โwho's onlineโ in a Grails or Java application?
- JSF: how to cancel a user session when it is registered twice using the same credentials
I modified the SessionData class to implement the HttpSessionBindingListener . When a binding event occurs, the object will either add or remove itself from the set of all SessionData objects.
@Override public void valueBound(HttpSessionBindingEvent event) { // Get my custom application-scoped attribute ApplicationData applicationData = getApplicationData(); // Get the set of all SessionData objects and add myself to it Set<SessionData> activeSessions = applicationData.getActiveSessions(); if (!activeSessions.contains(this)) { activeSessions.add(this); } } @Override public void valueUnbound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); ApplicationData applicationData = getApplicationData(); Set<SessionData> activeSessions = applicationData.getActiveSessions(); if (activeSessions.contains(this)) { activeSessions.remove(this); } }
The only thing that annoys me is what happens when Tomcat restarts. If Tomcat was not configured correctly to NOT serialize sessions to disk, it will do so. When Tomcat starts again, the HttpSession objects (and the SessionData objects along with them) are deserialized and the sessions become valid again. However, serializing / deserializing completely bypasses the HttpSession events of the listener, so I have no way to gracefully put the deserialized reference to the SessionData back into the managed set of objects after restarting.
I have no control over the production configuration of Tomcat in my client organization, so I cannot assume that this will be done as I expect.
My workaround is to compare the time the HttpSession with the time the application started when it received the request. If the session was created before the application started, I call invalidate() , and the user is sent to the error / warning page explaining what happened.
I get the application startup time by implementing the ServletContextListener and saving the current time inside the object with the application scope from the contextInitialized() method of my listener.
Jim Tough Sep 22 '10 at 15:50 2010-09-22 15:50
source share