Adam Bien's Weblog
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]
Posted at 10:31AM Oct 14, 2009 by Adam Bien in Real World Java EE Patterns - Rethinking Best Practices | Kommentare[7]
[my tweets]
Rss My book: Real World Java EE - Rethinking Best Practices


hi adam!
This seems not to work on WebSphere...
regards gustav
Gesendet von gustav am October 15, 2009 at 10:24 AM CEST #
dependency injection of TransactionSynchronizationRegistry fails in Interceptor and Entity-Listener.
JNDI Lookup works.
regards gustav
Gesendet von gustav am October 15, 2009 at 10:27 AM CEST #
But "KEY" itself is also context, which also needs to be passed around, so there is always something that you need to pass either via the callstack or via a thread-local kind of thing, no?
(Unless it's global - but then, the context itself becomes global, and passing data this way goes somewhat against information hiding).
Gesendet von Dimitris Andreou am October 15, 2009 at 11:49 AM CEST #
Hi Adam,
sounds cool and seems to work, so we might get rid of our ThreadLocal dependecies! How the **** did you find this class?
Thanks,
Norbert
@Dimitris: The key is local to a transaction. When using the same key within concurrent transactions it will reference different values.
Gesendet von Norbert Seekircher am October 15, 2009 at 05:19 PM CEST #
@Gustav,
1. "This seems not to work on WebSphere..." - then you will have to open an issue. It is a part of the spec.
2. "dependency injection of TransactionSynchronizationRegistry fails in Interceptor and Entity-Listener.
JNDI Lookup works." Works as designed - you cannot inject anything into JPA. A JNDI-lookup should work.
thanks for your feedback!,
adam
Gesendet von Adam Bien am October 15, 2009 at 09:10 PM CEST #
@Dimitris,
the key is just a constant. The value of the key is local to a transaction. Information hiding between layers is another issue. This technique is often used to pass additional information like security information or handle to a transaction-specific resource...
thanks!,
adam
Gesendet von Adam Bien am October 15, 2009 at 09:13 PM CEST #
@Norbert,
"How the **** did you find this class?"
A customer asked me during a review about my opinion about this approach :-). I found that in J2EE 1.4 spec and it worked well even at that time.
With Java EE 5 it not only works, but is really nice!,
thanks for your feedback,
adam
Gesendet von Adam Bien am October 15, 2009 at 09:14 PM CEST #