Discussions

Web tier: servlets, JSP, Web frameworks: Session Management

  1. Session Management (1 messages)

    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.

    Threaded Messages (1)

  2. Session Management[ Go to top ]

    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.