Java ThreadLocal and It's use


Have you ever wondered about accessing you HTTPServletRequest object (or any other contextual/scoped object) in a non web class? What I mean by non web class is any class that does not goes through a web request/response initialization life cycle. HttpServlet is a web class because web container initializes and provides the HttpServletRequest and HttpServletResponse objects.

Let’s say you have a POJO and you want to initialize few properties/variables of it from request object/parameters. Since the POJO is plain class it by default does not have access to the request object, then how to get access if current request Object? We have two options:

1.       Override the public constructor of POJO class to accept HttpServletRequest as an argument
e.g. public MyClass(HttpServletRequest request) { }

When we are forcing a class’s constructor to accept an Object, we always need to make sure that we are passing it and the class is tightly coupled with the underlying implementation. Also, we can not instantiate it without passing required arguments or null.

2.       Use the thread local capabilities of Java: Thread Local can be considered as a scope of access, like a request scope or session scope. It’s a thread scope. You can set any object in Thread Local and this object will be global and local to the specific thread which is accessing this object. Let’s take a look at the class that uses the thread local concept and then I’ll explain the code:

import java.util.LinkedList;
import javax.servlet.http.HttpServletRequest;

public abstract class RequestUtil {
private static ThreadLocal> threadLocalRequest =
new ThreadLocal>();

                public static void setRequest(HttpServletRequest request) {
                                LinkedList list =  threadLocalRequest.get();
                                if (list == null) {
                                                list = new LinkedList();
                                                threadLocalRequest.set(list);
                                }
                                list.addLast(request);
                }

                public static HttpServletRequest getRequest() {
                                LinkedList list =  threadLocalRequest.get();
                                if (list != null && list.size() > 0) {
                                                return list.getLast();
                                };
                                return null;
                }

                public static void clearRequest() {
                                LinkedList list = threadLocalRequest.get();
                                if (list != null && list.size() > 0) {
                                                list.removeLast();
                                };
                }
}


So what we are doing here is, we just created a simple class that has three static methods setRequest(),getRequest() and clearRequest() for setting, fetching and clearing request object from thread local scope. At the entry point of request (e.g. service or doGet or doPost method) we just need to call

RequestUtil.setRequest(request);

This will set the request object in thread local context/scope, and to access it from anywhere (any class) where we don’t have access to request object we just need to call:
       
RequestUtil.getRequest();

This call will always make sure that it returns the current request object in current thread.

If you explicitly want to clear the current request object from thread local scope just to make sure that it not accessible to any other then just call:

RequestUtil.clearRequest();
       
I hope this will help you to implement some useful piece of functionality in your application. You can refer the java doc for more information http://download.oracle.com/javase/1.4.2/docs/api/java/lang/ThreadLocal.html

Comments

Popular posts from this blog

AEM as a Cloud Service (AEMaaCS) – Architecture Overview

AEM 6.3 - Bundle Whitelisting - Deprecation of administrative authentication

AEM - Query list of components and templates

Custom synchronisation or rollout action for blueprint ?