Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-2412

HttpSessionListener23 creates sessions which can cause StackOverflowException when creating HttpSessions

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Normal Normal
    • None
    • 6.5.7
    • None
    • None

      I have developed a service that receives heartbeats via js from the browser. The purpose is to detect when the user has closed the tab (which cannot be detected reliably via events) and to invalidate the session and release locks in such cases.
      This required implementing a javax.servlet.Filter which basically reimplements the servlet session.timeout. In this filter I get the HttpSession and set a session attribute. I do this by wrapping the request into a custom class:

      private static class SessionAccessUpdatingRequest extends HttpServletRequestWrapper {
      
        SessionAccessUpdatingRequest(HttpServletRequest request) {
          super(request);
        }
      
        @Override
        public HttpSession getSession() {
          return getSession(true);
        }
      
        @Override
        public HttpSession getSession(boolean create) {
          HttpSession session = super.getSession(create);
          if ( session != null ) {
            session.setAttribute(LAST_ACCESSED_TIME, System.currentTimeMillis());
          }
          return session;
        }
      }
      

      This service is not aware of ZK and this is how it is supposed to be. Now I run into the situation that setting a session attribute in a SessionListener triggers the above mentioned HttpSessionListener23 which in turn creates new sessions by calling getSession(true) on the request which causes a loop and hence a stack overflow:

      at com.tn_ag.ws.heartbeat.HeartbeatTimer.init(HeartbeatTimer.java:70)
      	at com.tn_ag.ws.heartbeat.SessionListener.sessionCreated(SessionListener.java:42)
      	at org.mortbay.jetty.servlet.AbstractSessionManager.addSession(AbstractSessionManager.java:575)
      	at org.mortbay.jetty.servlet.AbstractSessionManager.newHttpSession(AbstractSessionManager.java:413)
      	at org.mortbay.jetty.Request.getSession(Request.java:1243)
      	at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:227)
      	at com.tn_ag.ws.heartbeat.SessionInvalidationFilter$SessionAccessUpdatingRequest.getSession(SessionInvalidationFilter.java:114)
      	at org.zkoss.zk.ui.http.WebManager.getSession(WebManager.java:426)
      	at org.zkoss.zk.ui.http.SessionResolverImpl.getSession(SessionResolverImpl.java:37)
      	at org.zkoss.zk.ui.Sessions.getCurrent(Sessions.java:57)
      	at org.zkoss.zk.ui.Sessions.getCurrent(Sessions.java:45)
      	at org.zkoss.zk.ui.http.HttpSessionListener23.attributeAdded(HttpSessionListener23.java:55)
      	at org.mortbay.jetty.servlet.AbstractSessionManager$Session.setAttribute(AbstractSessionManager.java:1073)
      	at com.tn_ag.ws.heartbeat.HeartbeatTimer.init(HeartbeatTimer.java:70)
      	at com.tn_ag.ws.heartbeat.SessionListener.sessionCreated(SessionListener.java:42)
      	at org.mortbay.jetty.servlet.AbstractSessionManager.addSession(AbstractSessionManager.java:575)
      

      I can break this cycle by changing the custom request class such that it is aware that getSession(true) was already called. However, I think it is not correct that the listener for setting attributes tries to create a new session because it should be the case that a session exists when an attribute is set for the session.

            Unassigned Unassigned
            avidD avidD
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: