[concurrency-interest] JTaP article on stateful web apps

Kris Schneider kschneider at gmail.com
Wed Sep 24 17:23:44 EDT 2008


The latest Java Theory and Practice article:

http://www.ibm.com/developerworks/library/j-jtp09238.html

exposes some of the concurrency issues that arise from using
HttpSession and ServletContext attributes. At the end of the "Possible
solutions" section, there's a reference to using SpringMVC's
synchronizeOnSession property of AbstractController to serialize
access to the session. After looking at the related code:

http://springframework.cvs.sourceforge.net/springframework/spring/src/org/springframework/web/servlet/mvc/AbstractController.java?view=markup
http://springframework.cvs.sourceforge.net/springframework/spring/src/org/springframework/web/util/WebUtils.java?view=markup
http://springframework.cvs.sourceforge.net/springframework/spring/src/org/springframework/web/util/HttpSessionMutexListener.java?view=markup

It seems like it's hiding its own dark corners. For example, in
AbstractController:

public abstract class AbstractController extends WebContentGenerator
implements Controller {
    private boolean synchronizeOnSession = false;

    public final void setSynchronizeOnSession(boolean synchronizeOnSession) {
        this.synchronizeOnSession = synchronizeOnSession;
    }

    public final boolean isSynchronizeOnSession() {
        return this.synchronizeOnSession;
    }

    public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
        // Delegate to WebContentGenerator for checking and preparing.
        checkAndPrepare(request, response, this instanceof LastModified);

        // Execute handleRequestInternal in synchronized block if required.
        if (this.synchronizeOnSession) {
            HttpSession session = request.getSession(false);
            if (session != null) {
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized (mutex) {
                    return handleRequestInternal(request, response);
                }
            }
        }
		
        return handleRequestInternal(request, response);
    }
...

If an instance of that class is shared between request threads, isn't
there a visibility (and publication?) issue with synchronizeOnSession?

The handleRequest method uses WebUtils.getSessionMutex to obtain the
lock object. Here's what that method looks like:

public static Object getSessionMutex(HttpSession session) {
    Assert.notNull(session, "Session must not be null");
    Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE);
    if (mutex == null) {
        mutex = session;
    }
    return mutex;
}

So, if the mutex attribute doesn't exist, the session object itself is
returned. Whether or not that will actually work is completely up to
the servlet container. There are no guarantees from the servlet spec
that the same instance is always returned from calls to
HttpServletRequest.getSession (let alone all the other ways that a
session object can be obtained). To be fair, the documentation for
getSessionMutex alludes to that fact, but then why not do something
like throw IllegalStateException in the case where the attribute
doesn't exist?

-- 
Kris Schneider <mailto:kschneider at gmail.com>


More information about the Concurrency-interest mailing list