Vaadin Applications, EJBs and JEE6

Hello folks,


Here
is a fresh article on how to inject EJBs directly into Vaadin Applications using JEE 6. Please read and comment!

Best regards,

-Petter-

Peter, a great and value article, especially about EJB injections ! Many thanks !

Im sure this will be very useful for JEE developers !

Regarding the performace: Im not sure first way should run into great performance problems - it seems to be a normal usage of stateful bean. Well, the resource usage to app server might increase as there will be more active stateful beans , especially if avg application lifetime is long. The only thing which needs to be done with care - transactions demarcation and and JPA beans usage in terms of transactions - one would need to mark transaction start/end points, in order not to end up creating single transaction on app start and committing it on app closure - this may lead to memory usage and data visibility issues.

I linked the article to DZone:
http://www.dzone.com/links/using_vaadin_as_ui_layer_for_jee6_applications.html

Please vote it up there if you like the it!

Hello again,


Here
is a demonstration video for the article. The quality is not the best, but it’ll have to do for now. I’m working on getting a better quality video up and running, but it may take a while.

-Petter-


Here
is the higher quality version.

-Petter-

Interesting, that’s after creating vaadin apps using CDE, ThreadLocal pattern does not work anymore, Application.getCurrentApplication returns null…

Actually, things even more interesting - Application.getCurrentApplication() works partially - some calls to getCurrentApplication ( which just calls threadlocal.get() ) may return null or may return a correct instance.

After some quick investigation I found the reason - here is the current code to capture app instance in my application class:

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

public static TPTApplication getCurrentApplication()
{
   currentApplication.get();
}

if I remove the condition in transactionStart(…) and just leave the method with single line, everything works just fine:

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

public static TPTApplication getCurrentApplication()
{
   currentApplication.get();
}

It seems, under CDI something works a bit differently. However, the core reason is still unclear for me, however, the quickfix above makes ThreadLocal pattern usable again.

Any ideas ?

Hmm… I thik that the condition is important. So, if the transaction listener gets called to every http request of every application in the session. I admit that several application instances in a single session is something that I have very rarely seen, but still.

I guess that the wrong instance you are experiencing are because of the fact that thread local is only updated if the condition was true - leaving old app instances.

I know very little about CDI and scoping, but what bothers me is how are the references to instances of inner classes (here transaction listener) of a session scoped application handled…

It is even interesting as at the moment of reproduction, there should be only one app instance - app server was just started, app deployed and single browser opened.

I attached log output to my app class constructor and now see that app instance is created 2 times (at least I do see double debug outputs) when a new application starts…

Im also new to CDI and JEE6 features, so probably Petter will have better idea on what’s could be wrong. I think this is important question to clarify, as since I cannot inject my app instance to other components such as Windows and Panels (or it is possible ? but I did not find the way to do so), ThreadLocal pattern still remains actual.

I will look into it ASAP.

-Petter-

are transactionStart / transactionEnd method invoked for any application in any session or only in current session ? I guess firts, so in case of 50 users using app1 and 50 users using app2 (so we have 100 instances in total), tx start/end methods will be called 100 times for every app instance (both app1 and app2), am I right ?

Update: I’ve been reading the JSR-299 specification, but I still have not found a solution to the problem. I will continue the investigation later - now I have to concentrate on getting JPAContainer ready for release.

-Petter-

Hi.

Yours article was very useful, however I have some problem with @SessionScoped annotation in my application class (called MyApplication :slight_smile: ).
My code looks like code in Option 2 in article, no magic is done.
After session timeout I get this exception on may application server (Glassfish 3.0):

SEVERE: Could not remove application, leaking memory.
SEVERE: javax.enterprise.context.ContextNotActiveException: No active contexts for scope type javax.enterprise.context.SessionScoped
at org.jboss.weld.BeanManagerImpl.getContext(BeanManagerImpl.java:928)
at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.getProxiedInstance(ClientProxyMethodHandler.java:140)
at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:101)
at com.demo.MyApplication_$$javassist_19.close(MyApplication$$_javassist_19.java)
at com.vaadin.terminal.gwt.server.AbstractWebApplicationContext.valueUnbound(AbstractWebApplicationContext.java:116)
at org.apache.catalina.session.StandardSession.removeAttribute(StandardSession.java:1552)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:857)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:761)
at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:678)
at org.apache.catalina.session.StandardManager.processExpires(StandardManager.java:1006)
at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5667)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1781)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1770)
at java.lang.Thread.run(Thread.java:619)

I have no idea why I get this excpetion. Do you have any clue what’s wrong ?

Hello,

Do you have a @Remove annotation on the application’s close() method?

Apparently, there seems to be a lot of stuff going on under the hood that causes Vaadin to act strangely on some occasions when CDI is used. I’m going to look into it as soon as I have time.

-Petter-

Thank you for fast replay.

I have used @Remove annotation, but that didn’t help (close method wasn’t call when container expired session). I think that this annotation work only In Stateful EJB beans.
I don’t want to use statefull EJB bean for my application class because of performance issues.

Hi,

I’m having the same problem reported by Dawid. I’m using Glassfish v3 and vaading 6.2.5.

Anyone have a clue?

Hello,

The reason why I asked about the @Remove-annotation was to make sure you didn’t use it, as it should not be necessary. :wink:

I’m currently unable to reproduce the problem, the code from the article runs fine on my end. Could you please post the code and some more information about when exactly the exception occurs?

-Petter-

When using CDI, the application server handles the scope of all the beans. Thus, if I’m not entirely mistaken, there should be no need for a ThreadLocal pattern at all. Ordinary fields should do just fine.

I’m still trying to figure out the correct way of injecting a session scoped application into e.g. a window or a custom component. The other way around should not be a problem, i.e. injecting components and windows into your application instance.

-Petter-

May I ask why you want to inject the application instance into your components? Shouldn’t you be able to use the Component.getApplication() -method, or do you need the instance before the components have been added to the application?