Scenario:
I have a servlet named Controller which is setup to receive all incoming requests for a particular url-pattern. This controller registers itself in the ServletContext as an attribute. There is a SessionListener named SessionController that loads the Controller from the ServletContext and calls a method in the Controller anytime a session is created or destroyed. The controller then creates a PageLoader and maps that into a Hashtable using the Session as the key.
Problem:
When a new session is created, all things work as expected. The Controller creates a PageLoader, adds it to the hashtable with Session as the key. All service requests are routed to the PageLoader referenced by the corresponding session component.
However, when the session is destroyed, the ID of the destroyed session is different than the ID of the same session when it was created, and therefore the Controller cannot successfully remove the PageLoader, as it cannot find it.
I am running Tomcat 4.1.24 with JDK 1.4.1. Details below:
/*********
* Web.xml
*********/
<web-app>
<listener>
<listener-class>com.linxpda.webapp.listeners.SessionController</listener-class>
</listener>
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>com.linxpda.webapp.Controller</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>/webapp/*</url-pattern>
<servlet-mapping>
</web-app>
/*********
* Controller.java
*********/
package com.linxpda.webappp;
.....
public class Controller extends HttpServlet {
Hashtable loaders;
public void init(ServletConfig config) throws ServletException {
if (loaders == null) {
loaders = new Hashtable(1, 1);
}
(config.getServletContext()).setAttribute("Controller", this);
System.out.println("Initialized Controller Servlet");
}
public void addLoader(HttpSession session) {
if (! loaders.containsKey(session)) {
loaders.put(session, new PageLoader());
System.out.println("Added loader for Session ID#: " + session.getId());
}
}
public void removeLoader(HttpSession session) {
if (! loaders.containsKey(session)) {
System.out.println("Unable to remove loader for Session ID#: " + session.getId());
}
else {
PageLoader loader = (PageLoader) loaders.get(session);
loaders.remove(loader);
loader = null;
if (loaders.isEmpty()) {
loaders = null;
}
else {
Enumeration keys = loaders.keys();
System.out.println("Still contain loaders for: \n");
while (keys.hasMoreElements()) {
System.out.println("Session ID#: " + (HttpSession) keys.nextElement()).getId());
}
}
System.out.println("Removed loader for Session ID#: " + session.getId());
}
}
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
HttpSession session = ((HttpServletRequest) request).getSession();
PageLoader loader = (PageLoader) loaders.get(session);
loader.processRequest(request, response);
System.out.println("Serviced Session ID #: " + session.getId());
}
public void destroy() throws ServletException, IOException {
super.destroy();
}
}
/*********
* SessionController.java
*********/
package com.linxpda.webapp.listeners;
.......
public class SessionController implements HttpSessionListener {
public void sessionCreated(HttpSession session) {
((Controller) session.getServletContext().getAttribute("Controller")).addLoader(session);
}
public void sessionDestroyed(HttpSession session) {
((Controller) session.getServletContext().getAttribute("Controller")).removeLoader(session);
}
}
Sample output:
.....
Initialized Controller Servlet.
.....
Added loader for Session ID #: 995ED67E7A7AA682E9939
Serviced Session ID#: 995ED67E7A7AA682E9939
Serviced Session ID#: 995ED67E7A7AA682E9939
Serviced Session ID#: 995ED67E7A7AA682E9939
Unable to remove loader for Session ID#: 628E3EB3C72893EE96532C8
Still contain loaders for:
Session ID#: 995ED67E7A7AA682E9939
There was only one session created (as evidenced by only one Added loader statement). But when the session was terminated, it has a different ID.
Any help would be greatly appreciated.
-
Session Management (1 messages)
- Posted by: Tom Cole
- Posted on: December 22 2003 20:50 EST
Threaded Messages (1)
- Session Management by Paul Strack on December 23 2003 10:35 EST
-
Session Management[ Go to top ]
- Posted by: Paul Strack
- Posted on: December 23 2003 10:35 EST
- in response to Tom Cole
The servlet spec discourages you from using the Session ID for any kind of storage. I have two suggestions:
1) Store your PageLoader directly in the session itself rather than an external HashMap. That way it will be garbage collected along with the session itself.
2) Even better, see if you can make the PageLoader independent of a user's session. There should not be a need to have a separate page loader for each user, unless you are doing something strange.