Adam Bien's Weblog

Wednesday Oct 14, 2009

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]


[my tweets]  Rss My book: Real World Java EE - Rethinking Best Practices

Kommentare:

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 #

Senden Sie einen Kommentar:
  • HTML Syntax: Ausgeschaltet
Interviews/About
My Recent Book
Java One 2009
CommunityOne East N.Y.C
JavaONE 2008 Interview
Search
...the last 150 posts
...the last 10 comments
greenfire.dev.java.net
Links
my.netbeans.org
Visitors
License