CDI & ThreadLocal

We finally figured out the problem why ThreadLocal pattern does not work when Vaadin application instance is created on JEE6 compatible app server using CDI.

The main problem is that when you’re using injections and inject the SessionScoped application instance to a application servlet, actually this becomes not your application instance but the generated proxy class - this is done by the CDI congtainer transparently. This proxy class extends your actual class and delegates all methods invocation to an correct actual, real instance of your class.

But this is the reason, why the following code in the ThreadLocal pattern does not work anymore:

public void transactionStart ( Application application, Object o )
   {
       if ( application == this )
       {
           currentApplication.set ( this );
       }
   }

The “if” statement will not work here because instances will not match due to proxy object over the actual instance.

So, here is the solution to get it working back. It is backwards compatible and will work with non CDI environments.

First, in your application class, make the extra methos, which returns self. Then, in your transaction start/end listeners, tweak the condition a bit:


public class MyApplication extends Application()
{
   public MyApplication()
   {
      super();
      ...
   }

   public Application getSelf()
   {
      return this;
   }
   ...
   ...

   public void transactionStart ( Application application, Object o )
   {
       if ( application instanceof MyApplication && ((MyApplication)application).getSelf() == this )
       {
           currentApplication.set ( this );
       }
   }

   public void transactionEnd ( Application application, Object o )
   {
       if (application instanceof MyApplication && ((MyApplication)application).getSelf() == this )
       {
           currentApplication.remove ();
       }
   }

   ...
   ...
}

So, calling getSelf() in our “if” block will always return the exact instance of an application, not a proxy and ThreadLocal pattern will work fine with CDI.

I think, we need to adjust the information on a wiki (manual) for the explanation of a ThreadLocal pattern as well onthe page which describes how to use Vaadin app with JEE6 - both via CDI or SessionBean. Id make the changes but not familiar with the LifeRay’s wiki, so if anyone made such changes or will give me a glue how to edit wiki pages here, Id be thankful.

Best,
Dmitri

For those who’re using my
TPT
add-on, fix for this is committed to the rev 27 to the svn trunk, also Im attaching the pre-build tpt-core.jar here for quick access. New TPT release will be expedited soon.
11289.jar (340 KB)

If the bean is @SessionScope then in fact you have a proxy. Adding getSelf doesn’t help a lot in my opinion. Look that getSelf is a proxy method also. So it will return the pointer to the proxy class, not the real one.

Right? Or do I miss something?

Yes, things get tricky quickly if you start trying to work around what the container is doing for you. I’m happy not trying to get it to manage objects it doesn’t need to. :slight_smile: (This is coming from someone who worked for many years on the Java EE reference implementations.)

Can I ask what may be a dumb question: why are you trying to implement something like this anyway? Vaadin components can just call getApplication() during the attach() or any business method, right? I’ve seen some traffic about lots of ways to store the proper instance of a Vaadin Application during a call, but as far as I can tell the proper instance is already stored in each component when it’s added to the application. I’m probably missing a large class of use cases.

Thanks,
Bobby