This one is related to J2EE application development. Often application developers and a lot of architects are skeptical in working with threads in a managed environment. Loads and loads of java applications that run on high end app servers are getting written. And most of them have the application architected in several layers. I will present below an approach which would help propagate various information “clandestinely” within the application. This is not something new and many frameworks like hibernate (for session binding) use these approaches internally…so what is this all about??? Read further…
The J2EE application servers as well all know work with threads internally so when a given request is being processed, it is attached to its own thread of execution. Even if you are application concerns are well split into multiple layers, the same thread will go layer after layer and execute code. This is something that could be leveraged by applications smartly. Assume for instance I have a typical J2EE application that has a front end layer and a business logic/service layer. There could be backend interactions using implementations of the DAO pattern. It many applications, there could be app-wide information that is required to be used across many layers (example – user information). If there is some way to propagate this information to all layers without having to pass it to all methods, then it will make code that much cleaner and individual coders need not worry about many intricacies. This is where the current thread context comes in handy.
Here is the strategy -Get a handle to the currently executing thread and then set the value in it(user information in our example). You are done now – this information is available throughout the thread of execution…..lets look at sample code below,
public class ThreadContext {
private static ThreadLocal<ThreadContext> threadCtx = new InheritableThreadLocal<ThreadContext>();
/** Map of objects that can be added into the thread context **/
private final Map<String, Object> ctxMap = new HashMap<String, Object>();
/**
* <p>This method is to set an object into the thread context</p>
* @param key
* @param value void
*/
private void putObjInContext(String key,Object value) {
this.ctxMap.put(key, value);
}
/**
* <p>This method is to get an object from the thread context</p>
* @param key
* @return Object
*/
private Object getObjFromContext(String key) {
return this.ctxMap.get(key);
}
ThreadContext(){
//I have used a no argument constructor here. But if you want to default initialize
//anything you can use this place
}
public static ThreadContext getThreadContext(){
return threadCtx.get();
}
/**
* <p>Set the context back into the current thread</p>
*/
public static void setThreadContext(ThreadContext ctx){
threadCtx.set(ctx);
}
}
Here is the usage. Wherever the context is needed, this is what you should do..
ThreadContext.getContext().getObjFromContext(key);
Once the current request is processed, all the context related information is purged and the thread if returned to the pool. It is guaranteed that any information you put on the thread will remain synchronized so no one else other than the current user who is being served can access it. Secondly, once the execution is complete and before the thread if handed back into the pool all information is purged so data will not get shared.