How To Pass Context In Standard Way - Without ThreadLocal 📎
javax.transaction.TransactionSynchronizationRegistry holds a Map-like structure and can be used to pass state inside a transaction. It works perfectly since the old J2EE 1.4 days and is thread-independent.
Because an Interceptor is executed in the same transaction as the ServiceFacade, the state can be even set in a @AroundInvoke method. The TransactionSynchronizationRegistry (TSR) can be directly injected into an Interceptor:
public class CurrentTimeMillisProvider {
@Resource
private TransactionSynchronizationRegistry registry;
@AroundInvoke
public Object injectMap(InvocationContext ic) throws Exception{
registry.putResource(KEY, System.currentTimeMillis());
return ic.proceed();
}
}
A ServiceFacade don't even has to inject the TSR. The state is automatically propagated to the invoked service:
@Stateless
@WebService
@Interceptors(CurrentTimeMillisProvider.class)
public class ServiceFacadeBean implements ServiceFacade {
@EJB
private Service service;
public void performSomeWork(){
service.serviceInvocation();
}
}
Everything, what is invoked in the scope of a ServiceFacade - and so its transaction has access to the state stored in the injected TSR:
@Stateless
public class ServiceBean implements Service {
@Resource
private TransactionSynchronizationRegistry tsr;
public void serviceInvocation() {
long timeMillis = (Long)tsr.getResource(KEY);
//...
System.out.println("Content is " + timeMillis);
}
}
TransactionSynchronizationRegistry works (should work) even in case you had assigned different thread pools to EJBs, which participate in the same transaction. The state would get lost with a simple ThreadLocal.
Because we are already in the lightweight Java EE 5 / 6 world - XML and other configuration plumbing are fully optional :-).
A deployable, working example (ContextHolder) was tested with Glassfish v3 and NetBeans 6.8m2 and pushed into http://kenai.com/projects/javaee-patterns/.
[See Context Holder pattern, page 247 in "Real World Java EE Patterns Rethinking Best Practices" book for more in-depth discussion]