ThreadLocal to store ServletRequest and Response in servlet: what for?
Since the request and the response objects are stored in thread local variables, you get thread safe access to those objects without having to pass them around as method parameters.
Example 1: Without thread local
public class MyServlet extends Servlet {
private MyObject myObject = new MyObject();
public void service(ServletRequest request, ServletResponse response) {
myObject.doSomething(request, response);
}
}
public class MyObject {
private MyOtherObject myOtherObject = new MyOtherObject();
public void doSomething(ServletRequest request, ServletResponse response) {
// I do nothing with request/response, but need to accept them in order
// to pass them to myOtherObject
myOtherObject.doSomethingElse(request, response);
}
}
public class MyOtherObject {
public void doSomethingElse(ServletRequest request, ServletResponse response) {
// Do something else with request / response
}
}
Example 2: with thread local
public class MyServlet extends Servlet {
private MyObject myObject = new MyObject();
private static ThreadLocal<ServletRequest> currentRequest = new ThreadLocal<ServletRequest>();
public static ServletRequest getCurrentRequest() {
return currentRequest.get();
}
private static ThreadLocal<ServletResponse> currentResponse = new ThreadLocal<ServletResponse>();
public static ServletResponse getCurrentResponse() {
return currentResponse.get();
}
public void service(ServletRequest request, ServletResponse response) {
...
currentRequest.set(request);
currentResponse.set(response);
...
myObject.doSomething();
}
}
public class MyObject {
private MyOtherObject myOtherObject = new MyOtherObject();
public void doSomething() {
// I do not need to know about request / response as I do nothing with them
myOtherObject.doSomethingElse();
}
}
public class MyOtherObject {
public void doSomethingElse() {
// Now I can get the current request / response in a thread safe
// manner and without having to accept them as parameters
ServletRequest request = MyServlet.getCurrentRequest();
ServletResponse response = MyServlet.getCurrentResponse();
// Do something with request / response
}
}
Obviously, for simple servlets just passing the objects around is the easiest thing, but in complex scenarios it is sometimes useful to have one static but thread safe getter.
Others have pretty much stated what is the use of Thread Locals in the scenario you presented. But be warned though, Thread Local relying implementations are "thread" specific and break when things move away from a single thread per request model. Example would be event based servers wherein a handful of threads are used for lots of user requests concurrently.
The point is to have the request and response objects in classes that would otherwise would not have them (for example they are not servlets). One example are JSF managed beans - their methods do not take HttpServletRequest
parameters, and so you can obtain the request via the FacesContext
, which has them in ThreadLocal
variables.
The reason this works is because each request is handled by a separate thread (by the servlet container). So thread = request. But there is a caveat - containers tend to use thread pools. So one must always set a fresh request in the threadlocal, and preferably clean it up afterwards (for example in a Filter
). Otherwise you can get some unexpected behaviour.
But you should really avoid this in your code. If you need anything from the request or response, pass it as method argument around. Otherwise you risk to violate layer boundaries (if you are tempted to use the request in the service layer, for example)
They allow you to gain access to the HttpServletRequest and HttpServletResponse from other classes within your project without having to pass references to these objects to the other classes. It's not a pattern I particularly like as it tends to mix up your web tier code with your business logic and makes unit testing more difficult.