1 Reply Latest reply: Oct 12, 2011 4:41 AM by Sondre Bjornebekk RSS

    Oracle Coherence*Web and BlazeDS: Multiple FlexSessions created for the same HttpSession

    Sondre Bjornebekk Community Member

      Hi all,

       

      I have searched this forum and found a lot of good information from Alex Glosband and others about the infamous "Detected duplicate HTTP - based FlexSessions, generally due to the remote host disabling session cookies. Session coolkies must be enable to manage the client connection correctly." message.

       

      It seems, however, none of the cases are identical to ours. This is ours:

       

      - Resin 3.1.9

      - Oracle Coherence 3.7.1 with Coherence*Web (session replication)

       

      With this setup we get the "Detected duplicate HTTP..." message on the first attempt to use BlazeDS and on every subsequent call.  The same client and server code works fine in a local sessions setup.  With Coherence 3.3 (currently our production environment) it seems to occur less frequently, but still as frequent as it is a major issue for us.  It fails even with a single node using in-process distributed caching in our test setup (as well as with multi node out of process caching in our staging environment, for Coherence knowledgeable the resin app server runs with tangosol.coherence.session.localstorage=true in the first case and false in the second).

       

      Both the listener and message broker are mapped as "Coherence aware" in web.xml[1] so that they should use clustered sessions.

       

      We have been digging a bit and we found out that if we commented out lines 427 and 434 of flex.messaging.endpoints.BaseHTTPEndpoint from version 4.0.0.14931 it seems to mask the bug.  We added some logging in the setupFlexClient method and it seems that we get more or less a new FlexSession for each and every call - but they have the same cookie and thus underlying HttpSession. I.e. the list returned from flexClient.getFlexSessions() keeps growing. Thus we are not so keen on going to production with that memory leak and the above mentioned ugly hack of commenting out the detection of duplicates.

       

      We use request scope for the remote object, but could in theory use any scope as we do not really have any state on the object itself, it is all HttpSession state and return values that are key (logon is performed prior to doing the first blaze call, in pure forms and ajax, and it is not a timing issue in that regard we are seeing).

       

      Hope someone can shed some light on what can be happening. Is there any "reference testing"[2] or something when the FlexSessions are created that makes them being created as new? Where are they created?  We do not know the inner workings of the BlazeDS source, we just watched the call trace of the unwanted invalidation and found that to be line 427 of flex.messaging.endpoints.BaseHTTPEndpoint.

       

      Can we disable FlexSessions?  Since the flex and plain html parts of the app share the sessions, we always use FlexContext.getHttpRequest().getSession() anyway, never storing any state directly in the FlexSession or on the remote object. Or maybe there is a config option to help us with this detection (or creation) of multiple FlexSessions?

       

      Cheers and TIA,

       

      -S-

       

      [1] - For instance, this i the message broker servlet def:

       

      <servlet>

      <servlet-name>MessageBrokerServlet</servlet-name>

        <display-name>MessageBrokerServlet</display-name>

      <servlet-class>com.tangosol.coherence.servlet.api22.ServletWrapper</servlet-class>       

      <init-param>

      <param-name>coherence-servlet-class</param-name>

      <param-value>flex.messaging.MessageBrokerServlet</param-value>

      </init-param>       

      <init-param>

      <param-name>services.configuration.file</param-name>

      <param-value>/WEB-INF/flex/services-config.xml</param-value>

      </init-param>

      <load-on-startup>1</load-on-startup>

      </servlet>

       

      [2] - As you undertstand this is speculation based on pure air, but it could be that in Coherence there was a serialization/deserialization happening somehow that would break such a test?

        • 1. Re: Oracle Coherence*Web and BlazeDS: Multiple FlexSessions created for the same HttpSession
          Sondre Bjornebekk Community Member

          Just a quick update, it seems things are running in a stable fashion (and without visible memory leaks, just keeping the latest FlexSession) with these changes in BaseHTTPEndpoint:

           

          /**

               * Overrides to guard against duplicate HTTP-based sessions for the same FlexClient which will occur if the remote host has disabled session

               * cookies.

               * 

               * @see AbstractEndpoint#setupFlexClient(String)

               */

              @Override

              public FlexClient setupFlexClient(String id) {

                  log.debug("setupFlexClient start id " + id);

                  FlexClient flexClient = super.setupFlexClient(id);

           

                  // Scan for duplicate HTTP-sessions and if found, invalidate them and throw a MessageException.

                  // A request attribute is used to deal with batched AMF messages that arrive in a single request by trigger multiple passes through this

                  // method.

                  boolean duplicateSessionDetected = (FlexContext.getHttpRequest().getAttribute(REQUEST_ATTR_DUPLICATE_SESSION_FLAG) != null);

           

                  if (!duplicateSessionDetected) {

                      List<FlexSession> sessions = flexClient.getFlexSessions();

                      log.debug("Client has " + sessions.size() + " sessions.");

                      int n = sessions.size();

                      if (n > 1) {

                          int count = 0;

                          for (int i = 0; i < n; i++) {

                              if (sessions.get(i) instanceof HttpFlexSession)

                                  count++;

                              if (count > 1) {

                                  FlexContext.getHttpRequest().setAttribute(REQUEST_ATTR_DUPLICATE_SESSION_FLAG, Boolean.TRUE);

                                  duplicateSessionDetected = true;

                                  break;

                              }

                          }

                      }

                  }

           

                  // If more than one was found, remote host isn't using session cookies. Kill all duplicate sessions and return an error.

                  // Simplest to just re-scan the list given that it will be very short, but use an iterator for concurrent modification.

                  int i = 0;

                  if (duplicateSessionDetected) {

                      List<FlexSession> sessions = flexClient.getFlexSessions();

                      log.debug("Detected sessions from client: " + sessions);

                      for (FlexSession session : sessions) {

                          if (session instanceof HttpFlexSession && i < sessions.size()) {

          //                    log.debug("----> sessionId: " + session.getId());

          //                    Enumeration e1 = session.getAttributeNames();

          //                    while (e1.hasMoreElements()) {

          //                        Object key = e1.nextElement();

          //                        log.debug("--------->" + key + "--------->" + session.getAttribute((String) key));

          //                    }

           

          //                    session.invalidate();

                              flexClient.sessionDestroyed(session);

                          }

                          i++;

                      }

           

                      // Return an error to the client.

          //            DuplicateSessionException e = new DuplicateSessionException();

          //            e.setMessage(ERR_MSG_DUPLICATE_SESSIONS_DETECTED);

          //            throw e;

                  }

           

                  return flexClient;

              }

           

          It is not exactly beautiful (to say the least), but if it does the trick I might just be pragmatic enough to go with it... NB: I am of course not proposing this as a patch to this file or anything, it is just an ugly hack for our specific case, but maybe the information can help the BlazeDS team find the root cause making it incompatible with Coherence*Web.

           

          Will give it a test run on our staging servers.