Are CDI event observer methods compatible with EJBs?
I have a Singleton EJB (javax.ejb.Singleton version. sigh.) which has a CDI observer method on it. When I try to deploy this to glassfish 3.1 the server fails to deploy the EAR file without any real explanation - simply saying there was an exception during deployment without any more details.
SEVERE: Exception while loading the app
SEVERE: Exception while shutting down application container
....
SEVERE: Exception while shutting down application container : java.lang.NullPointerException
This is the CDI event listener :
public void updateFromGranule(@Observes @CloudMask GranuleAvailableEvent granuleEvent) {
LOG.info("updating cloud map");
update(granuleEvent.getGranule(), CloudMask.class);
fireUpdate();
}
If I change the Singleton bean to just be an @ApplicationScoped bean the app deploys fine. Similarly, if I remove the CDI event observer method the application deploys fine. I actually need the class to be an EJB singleton because I want the transaction, thread safety etc. of EJBs, so just leaving this as a @ApplicationScoped POJO isn't much use to me. The problem doesn't seem to be limited to Singleton beans though - I've experimented by changing the annotation to @Stateless and @Stateful and I get the same issue.
It seems to me that this might be a bug in Weld, perhaps Weld and EJB are fighting about how they proxy that method - presumably EJB needs to add an interceptor class and wrap that method to ensure thread safety, and Weld is tr开发者_开发百科ying to do something else to make the event listener work?
Am I misunderstanding something here, and should CDI event handlers simply not be used on EJBs (in which case there should be better error messages from glassfish) - or is this actually just a bug in the CDI or EJB implementation?
I think this is the answer :
CDI observer methods must apparently either be static or declared in the local interface of an EJB if the EJB declares a local interface. Normally if you try to declare an observer method that isn't in the local interface you get an exception from Weld like this :
org.jboss.weld.exceptions.DefinitionException: WELD-000088 Observer method must be static or local business method: [method] public org.stain.ObserverBean.testMethod(EventClass) on public@Singleton class org.stain.ObserverBean
For some reason glassfish does not report this exception properly when loading my EAR file and simply says Exception while loading the app
.
Adding the method to the local interface (or removing the interface declaration on the class) fixes the problem and allows the application to load normally.
I noticed the same problem with the latest version of weld. But if you add the @LocalBean annotation it will work with @Singleton and @Singleton @Startup.
精彩评论