1 Reply Latest reply on Feb 27, 2010 11:02 AM by Zabin Begum

    Concurrent requests; one invalidates the session, results in recursive loop of session creation

    dave atkins Newbie

      Hello,


      I noticed that we had an massive number of sessions on one of our tomcat nodes that hosts our modest Seam app. After some investigation I discovered this in the log



      2009-11-25 17:38:02,521 INFO  [org.jboss.seam.contexts.Contexts] starting up: org.jboss.seam.web.session
      2009-11-25 17:38:02,522 INFO  [org.jboss.seam.contexts.Contexts] starting up: org.jboss.seam.security.identity
      2009-11-25 17:38:02,522 INFO  [org.jboss.seam.contexts.Contexts] starting up: org.jboss.seam.web.session
      2009-11-25 17:38:02,522 INFO  [org.jboss.seam.contexts.Contexts] starting up: org.jboss.seam.security.identity
      2009-11-25 17:38:02,522 INFO  [org.jboss.seam.contexts.Contexts] starting up: org.jboss.seam.web.session


      This is repeated for thousands of lines.  After digging around the seam code I realised that if you have two concurrent requests and one invalidates the session before the other is finished, seam goes into an recursive loop of session creation (normally ended by stack overflow).  Here's some of the stack trace. Note that the first and last calls are looping:


      at org.jboss.seam.Component.newInstance(Component.java:2094)
           at org.jboss.seam.contexts.Contexts.startup(Contexts.java:304)
           at org.jboss.seam.contexts.Contexts.startup(Contexts.java:278)
           at org.jboss.seam.contexts.Lifecycle.beginSession(Lifecycle.java:209)
           at org.jboss.seam.contexts.ServletLifecycle.beginSession(ServletLifecycle.java:141)
           at org.jboss.seam.servlet.SeamListener.sessionCreated(SeamListener.java:45)
           at org.apache.catalina.session.StandardSession.tellNew(StandardSession.java:397)
           at org.apache.catalina.session.StandardSession.setId(StandardSession.java:369)
           at org.apache.catalina.session.ManagerBase.createSession(ManagerBase.java:828)
           at org.apache.catalina.session.StandardManager.createSession(StandardManager.java:291)
           at org.apache.catalina.connector.Request.doGetSession(Request.java:2312)
           at org.apache.catalina.connector.Request.getSession(Request.java:2075)
           at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:833)
           at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:216)
           at org.apache.catalina.core.ApplicationHttpRequest.getSession(ApplicationHttpRequest.java:545)
           at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:216)
           at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:216)
           at com.sun.faces.context.SessionMap.getSession(ExternalContextImpl.java:1002)
           at com.sun.faces.context.SessionMap.get(ExternalContextImpl.java:962)
           at org.jboss.seam.contexts.ServerConversationContext.get(ServerConversationContext.java:110)
           at org.jboss.seam.contexts.Contexts.lookupInStatefulContexts(Contexts.java:189)
           at org.jboss.seam.Component.getInstance(Component.java:1949)
           at org.jboss.seam.Component.getInstance(Component.java:1944)
           at org.jboss.seam.Component.getInstance(Component.java:1924)
           at org.jboss.seam.Component.getInstance(Component.java:1919)
           at org.jboss.seam.security.Identity.create(Identity.java:101)
           at sun.reflect.GeneratedMethodAccessor2896.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
           at org.jboss.seam.util.Reflections.invokeAndWrap(Reflections.java:144)
           at org.jboss.seam.Component.callComponentMethod(Component.java:2211)
           at org.jboss.seam.Component.callCreateMethod(Component.java:2134)
           at org.jboss.seam.Component.newInstance(Component.java:2094)


      This problem is partially documented here - https://jira.jboss.org/jira/browse/JBSEAM-2888, unfortunately this bugfix didn't solve the root cause of the problem.


      The problem is caused by the SessionMap used by ServerConversationContext.  Internally the session map uses HttpServletRequest.getSession(true) to retrieve the session, which creates a new session if the one defined on the HttpServletRequest is invalid or null.  Unfortunately, when the new session is created session listeners are informed before the session has been set on the HttpServletRequest.  Seam is one of these session listeners and creates a new Identity on session creation, which in turn accesses the SessionMap, still before the new Session has been set on the request.  This leads to an infinite recursive loop.


      The SessionMap used is returned by externalContext.getSessionMap(). One solution could be to implement our own SessionMap that doesn't attempt to create a new session if the current session is invalid or null, although I've no idea how this would impact on other Seam code.


      The problem is relatively easy to create.  In our application we have a search page that can take quite a while to complete a request.  If we log out of the application in another tab before the search has completed the problem arises.


      We're on Jboss 4.2.2 with the shipped Jboss Tomcat and Seam 2.2.1.  Can anyone confirm this problem?

        • 1. Re: Concurrent requests; one invalidates the session, results in recursive loop of session creation
          Zabin Begum Newbie

          Hello Everybody


          I have a problem related to this topic.  In my application when the first request is coming the session is getting created.  When the next request is coming it is not creating a new session, rather taking the same by which the business logic is executed for the latest request and displaying the output of the old request browser.  I want that whenever a new request goes a new session should be created which hopefully solve my problem.  I tried to create the session by this way:



          HttpSession newSession = request.getSession(true);
                    if(newSession.isNew()){
                         System.out.println("is new");
                         System.out.println("hotelid:"+request.getParameter("hotelid"));
                         System.out.println("session:"+newSession.getId());
                    }
                    RequestDispatcher rd = request.getRequestDispatcher("/ezeeLink/hotelWebPage.seam");
                    rd.forward(request, response);     



          But this is not helping.  First time it is creating the session but the for next request it is not creating a new session.   Can any body help in this.  It is really a big concern to me.