You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by ek...@apache.org on 2006/05/27 02:16:53 UTC

svn commit: r409780 - in /beehive/trunk/netui: src/pageflow/org/apache/beehive/netui/pageflow/ src/pageflow/org/apache/beehive/netui/pageflow/internal/ src/pageflow/org/apache/beehive/netui/pageflow/requeststate/ src/util/org/apache/beehive/netui/util/...

Author: ekoneil
Date: Fri May 26 17:16:53 2006
New Revision: 409780

URL: http://svn.apache.org/viewvc?rev=409780&view=rev
Log:
Changes to NetUI synchronization to facilitate synchronization on a session scoped lock.  Before, locking was performed only on the HttpSession instance; in some circumstances, this isn't a safe operation because the HttpSession implementation can vary (even within application containers).  This provides an HttpSessionListener that can be registered in web.xml in order to add a mutex object as a session attribute.  

This can be retrieved by callers that need to synchronize some kind of change to the session.  To enable this feature, simply add the following to a web application:

    <listener>
        <listener-class>org.apache.beehive.netui.pageflow.HttpSessionMutexListener</listener-class>
    </listener>

The listener is optional; if not registered, the HttpSession will be used for synchronization.

The NameService and DeferredSessionStorageHandler were changed to synchronize on this session mutex.

BB: self
Test: NetUI pass


Added:
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/HttpSessionMutexListener.java
Modified:
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java
    beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/requeststate/NameService.java
    beehive/trunk/netui/src/util/org/apache/beehive/netui/util/internal/ServletUtils.java
    beehive/trunk/netui/test/webapps/drt/web/WEB-INF/web.xml

Added: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/HttpSessionMutexListener.java
URL: http://svn.apache.org/viewvc/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/HttpSessionMutexListener.java?rev=409780&view=auto
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/HttpSessionMutexListener.java (added)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/HttpSessionMutexListener.java Fri May 26 17:16:53 2006
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.beehive.netui.pageflow;
+
+import java.io.Serializable;
+import javax.servlet.http.HttpSessionListener;
+import javax.servlet.http.HttpSessionEvent;
+
+import org.apache.beehive.netui.util.internal.ServletUtils;
+
+/**
+ * <p>
+ * Class that implements an {@link HttpSessionListener} that adds a mutex object to the
+ * {@link javax.servlet.http.HttpSession}.  This listener adds a session scoped attribute
+ * to the key {@link org.apache.beehive.netui.util.internal.ServletUtils#SESSION_MUTEX_ATTRIBUTE}
+ * that can be used as a safe reference to lock access to the session.
+ * </p>
+ * <p>
+ * To use this listener, it needs to be registered in <code>web.xml</code>.
+ * </p>
+ */
+public final class HttpSessionMutexListener
+    implements HttpSessionListener {
+
+    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
+        httpSessionEvent.getSession().setAttribute(ServletUtils.SESSION_MUTEX_ATTRIBUTE, new Mutex());
+    }
+
+    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
+        httpSessionEvent.getSession().removeAttribute(ServletUtils.SESSION_MUTEX_ATTRIBUTE);
+    }
+
+    /**
+     * An internal class that is instantiated per HttpSession to act as an object to use
+     * when locking an HttpSession.
+     */
+    private static final class Mutex implements Serializable {
+    }
+}

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java
URL: http://svn.apache.org/viewvc/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java?rev=409780&r1=409779&r2=409780&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DeferredSessionStorageHandler.java Fri May 26 17:16:53 2006
@@ -23,6 +23,7 @@
 import org.apache.beehive.netui.pageflow.PageFlowController;
 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
 import org.apache.beehive.netui.util.logging.Logger;
+import org.apache.beehive.netui.util.internal.ServletUtils;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
@@ -191,13 +192,15 @@
             _log.debug("Applying changes for request " + request.getRequestURI() +
                 ".  Identity: " + System.identityHashCode(request));
 
+        Object sessionMutex = ServletUtils.getSessionMutex(session);
+
         //
-        // Synchronize on the HttpSession in order to make the operation of applying changes from a request into
+        // Synchronize on the session mutex in order to make the operation of applying changes from a request into
         // the session atomic.  Atomicity is needed in order to ensure that the attributes set in the session via
         // "session.setAttribute(...)" are the same ones present when the "ensureFailover" call is made against the
         // ServletContainerAdapter.
         //
-        synchronized(session) {
+        synchronized(sessionMutex) {
 
             HashSet changedAttrs = getChangedAttributesList( request, false, true );
             if ( changedAttrs != null )
@@ -342,7 +345,7 @@
         // Start with the attribute names that are in the session.
         if (session != null) {
             for (Enumeration e = session.getAttributeNames(); e.hasMoreElements(); ) {
-                attrNames.add((String) e.nextElement());
+                attrNames.add(e.nextElement());
             }
         }
 

Modified: beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/requeststate/NameService.java
URL: http://svn.apache.org/viewvc/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/requeststate/NameService.java?rev=409780&r1=409779&r2=409780&view=diff
==============================================================================
--- beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/requeststate/NameService.java (original)
+++ beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/requeststate/NameService.java Fri May 26 17:16:53 2006
@@ -27,6 +27,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.beehive.netui.util.internal.ServletUtils;
+
 /**
  * This class implements a service that will name and track objects which implement the
  * <code>INameable</code> interface.  The typical use of this class is in the XmlHttpRequest
@@ -68,9 +70,10 @@
         if (session == null)
             throw new IllegalArgumentException("Session must not be null");
 
-        // synchronize on the session so we only create a single NameService
-        // within the session.
-        synchronized (session) {
+        Object sessionMutex = ServletUtils.getSessionMutex(session);
+        // Synchronize on a session wide mutex to ensure that only a single NameService object is
+        // created within a specific user session
+        synchronized (sessionMutex) {
             NameService nameService = (NameService) session.getAttribute(NAME_SERVICE);
             if (nameService == null) {
                 nameService = new NameService();

Modified: beehive/trunk/netui/src/util/org/apache/beehive/netui/util/internal/ServletUtils.java
URL: http://svn.apache.org/viewvc/beehive/trunk/netui/src/util/org/apache/beehive/netui/util/internal/ServletUtils.java?rev=409780&r1=409779&r2=409780&view=diff
==============================================================================
--- beehive/trunk/netui/src/util/org/apache/beehive/netui/util/internal/ServletUtils.java (original)
+++ beehive/trunk/netui/src/util/org/apache/beehive/netui/util/internal/ServletUtils.java Fri May 26 17:16:53 2006
@@ -27,8 +27,14 @@
 import java.io.PrintStream;
 import java.util.Enumeration;
 
-public class ServletUtils
-{
+import org.apache.beehive.netui.util.logging.Logger;
+
+public class ServletUtils {
+
+    private static final Logger LOG = Logger.getInstance(ServletUtils.class);
+
+    public static final String SESSION_MUTEX_ATTRIBUTE = ServletUtils.class.getName() + ".MUTEX";
+
     /**
      * Print parameters and attributes in the given request.
      * 
@@ -158,5 +164,32 @@
         ServletException servletException = new ServletException(cause);
         servletException.initCause(cause);
         throw servletException;
+    }
+
+    /**
+     * Returns a mutex object for the given {@link HttpSession} that can be used to lock
+     * a given session.  The semantics for locking on an HttpSession object are unspecified, and
+     * servlet containers are free to implement the HttpSession in such a way that acquiring a
+     * lock on the HttpSession itself is not safe.  When used in conjunction with NetUI's
+     * HttpSessionMutexListener, this method provides a lock that is 100% safe to use across
+     * servlet containers.  If the HttpSessionMutexListener is not registered in web.xml, the
+     * HttpSession itself is returned as the next best lock.
+     *
+     * @param httpSession the current session
+     * @return a mutex that can be used to serialize operations in a web application on the HttpSession
+     */
+    public static Object getSessionMutex(HttpSession httpSession) {
+        assert httpSession != null : "HttpSession must not be null";
+
+        Object mutex = httpSession.getAttribute(SESSION_MUTEX_ATTRIBUTE);
+        if(mutex == null)
+            mutex = httpSession;
+
+        assert mutex != null;
+
+        if(LOG.isDebugEnabled())
+            LOG.debug("Using session lock of type: " + mutex.getClass());
+
+        return mutex;
     }
 }

Modified: beehive/trunk/netui/test/webapps/drt/web/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/beehive/trunk/netui/test/webapps/drt/web/WEB-INF/web.xml?rev=409780&r1=409779&r2=409780&view=diff
==============================================================================
--- beehive/trunk/netui/test/webapps/drt/web/WEB-INF/web.xml (original)
+++ beehive/trunk/netui/test/webapps/drt/web/WEB-INF/web.xml Fri May 26 17:16:53 2006
@@ -10,11 +10,14 @@
         <param-name>jpf-secure-forwards</param-name>
         <param-value>true</param-value>
     </context-param>
-<!--
+
     <listener>
         <listener-class>org.apache.beehive.netui.pageflow.PageFlowContextListener</listener-class>
     </listener>
--->
+
+    <listener>
+        <listener-class>org.apache.beehive.netui.pageflow.HttpSessionMutexListener</listener-class>
+    </listener>
 
     <!-- Test Recorder Filter -->
     <filter>