Alex Rivera | Logout

Is there a generic RequestContext in Java servlet API?

Asked 2012-04-17T18:38:57.657
15

(I'm not sure exactly how to phrase the title here, and because of that I'm not really sure how to go about searching for the answer either.)

I have a Java servlet engine that handles requests. Say we have a doGet() request:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //set up user data

    //do whatever the user requested
    SomeClass c = new SomeClass();
    c.doSomething();
}

Now in doSomething(), I want to be able to access which user made the request. Right now I'm doing it by creating a Java object within the method and passing it to wherever I need it:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //set up user data
    MyUserObj userObj = new MyUserObj();
    userObj.setId('123');

    //do whatever the user requested
    SomeClass c = new SomeClass(userObj);
    c.doSomething();
}

By doing this, I have access to the instance of MyUserObj, and it can be further passed along in the application as needed.

I know in ASP.NET MVC3 I can acheive this by storing items/attributes for the current thread like this: HttpContext.Current.Items.Add("myId", "123"). HttpContext is then available in other functions without explicitly having to pass around an object.

Is there a way in Java to set some variables per request (or even set the MyUserObject to be accessed later) without passing the object through as a parameter?

Edit
Report

1 Answer

23

There isn't in the servlet API, but you can make your own pretty easily. (Some frameworks like spring-mvc, struts provide such functionality)

Just use a public static ThreadLocal to store and retrieve the object. You can even store the HttpServletRequest itself in the threadlocal and use its setAttribute()/getAttribute() methods, or you can store a threadlocal Map, to be agnostic of the servlet API. An important note is that you should clean the threadlocal after the request (with a Filter, for example).

Also note that passing the object as parameter is considered a better practice, because you usually pass it from the web layer to a service layer, which should not be dependent on web-related object, like a HttpContext.

If you decide that it is fine to store them in a thread-local, rather than passing them around:

public class RequestContext {
    private static ThreadLocal<Map<Object, Object>> attributes = new ThreadLocal<>();
    public static void initialize() {
        attributes.set(new HashMap<Map<Object, Object>>());
    }
    public static void cleanup() {
        attributes.set(null);
    }
    public static <T> T getAttribute(Object key) {
        return (T) attributes.get().get(key);
    }
    public static void setAttribute(Object key, Object value) {
        attributes.get().put(key, value);
    }
}

And a necessary filter:

@WebFilter(urlPatterns="/")
public class RequestContextFilter implements Filter {
     public void doFilter(..) {
         RequestContext.initialize();
         try {
             chain.doFilter(request, response);
         } finally {
             RequestContext.cleanup();
         }
     }
}
answered 2012-04-17T18:43:10.357

Your Answer