Thursday, August 02, 2007

Original Pattern: ServletRequest in ThreadLocal

After seeing Scala had elements of Erlang through Actors, I decided to take a closer look at the language. There is an interesting new web framework in Scala, called Lift. One drawback of Lift is that it seems to be very cutting edge and not that easy to grasp. While reading its source code, I stumbled upon a strange pattern: Storing the ServletRequest in a ThreadLocal .

I had not seen that before, and was wondering why one would do such a thing. It seems to be unintuitive. I found my answer through... GWT widgets. In this page, the author explain motivations behind doing such a thing:

While not 100% in tune with the MVC pattern, it is often convenient to access the servlet
container, the HTTP session or the current HTTP request from the business layer. The GWT-SL
provides several strategies to achieve this which pose a compromise in the amount of configuration
required to set up and the class dependencies introduced to the business code.

The easiest way to obtain the current HTTP request is by using the ServletUtils class
which provides convenience methods for accessing the HttpServletRequest and
HttpServletResponse instances. Please note that it makes use of thread local variables
and will obviously not return correct values if used in any other than the invoking thread.

Still one can doubt if this is good design. In my long experience of web apps in Java I never had the need to do such a thing. Have you seen that pattern before?

7 comments :

  1. Just look at the original com.google.gwt.user.server.rpc.RemoteServiceServlet class that has both #getThreadLocalRequest and #getThreadLocalResponse methods.

    ThreadLocals provide convenient means for making context information available during request processing (especially when unsure when and where it might be needed). The alternative would be introducing extra parameters to all of your methods.

    ReplyDelete
  2. App servers use it. JTA probably does. I've used it myself to store the equivalent of JDBC connections in applications. It can be a useful technique for thread-confinement,; it is explained in a bit more detail in Java Concurrency in Practice, which is great book about a very complex subject.

    ReplyDelete
  3. It's actually a pretty standard practice. Some packages such as Apache Axis can hold both the request and response in the MessageContext.

    Anytime you see a "context" object like that it's often just a class holding a

    public class SomeContext
    {
    private static ThreadLocal<SomeContext> curr =
    new ThreadLocal<SomeContext>();
    private HttpServletRequest req;
    private HttpServletResponse resp;
    private SomeOtherData data;

    private SomeContext() {};

    public static SomeContext getCurr()
    {
    return curr.get();
    }

    public static loadContext(
    HttpServletRequest request,
    HttpServletResponse response,
    SomeData some)
    {
    SomeContext current = new SomeContext();

    current.req = req;
    current.resp = response;
    current.data = some;

    curr.set(current);
    }
    }

    for example...

    ReplyDelete
  4. james: Java Concurrency In Practice is an excellent book, the best imho on java concurrency. Here what I found surprising is the specific case of ServletRequest put in the ThreadLocal not in the general use of the ThreadLocal.

    I know ThreadLocal is used here and there. One of the best use I have seen is in Hibernate, to maintain the session.

    Thanks to the other comments I have learnt ServletRequest in ThreadLocal is more widely used that first thought: GWT, Axis!

    To me it still feel a bit like Singleton, just making a global variable, which is generally a bad pattern but has its uses sometimes.
    http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial

    ReplyDelete
  5. I don't see it like a Singleton. Both this approach, and Singleton for that matter, are good for what they are good for. Some things.

    This approach does have its down sides. Of course it depends on a single thread serving a 'request'. I there is something asynchronous, it breaks down.

    ReplyDelete
  6. Little late to the picnic :)

    Does ThreadLocal still work in an asynchronous web server which may only have a few threads and use selectors to process requests? The reason I ask is I see more async modes avail for most app servers now. But I still see a lot of libraries using ThreadLocal.

    ReplyDelete