CDI 事件观察器方法与 EJB 兼容吗?
我有一个 Singleton EJB(javax.ejb.Singleton 版本。叹息。)它有一个 CDI 观察者方法。当我尝试将其部署到 glassfish 3.1 时,服务器无法部署 EAR 文件,没有任何真正的解释 - 只是说部署期间出现异常,没有任何更多详细信息。
SEVERE: Exception while loading the app
SEVERE: Exception while shutting down application container
....
SEVERE: Exception while shutting down application container : java.lang.NullPointerException
这是 CDI 事件侦听器:
public void updateFromGranule(@Observes @CloudMask GranuleAvailableEvent granuleEvent) {
LOG.info("updating cloud map");
update(granuleEvent.getGranule(), CloudMask.class);
fireUpdate();
}
如果我将 Singleton bean 更改为 @ApplicationScoped bean,则应用程序部署正常。同样,如果我删除 CDI 事件观察器方法,应用程序部署正常。 我实际上需要该类成为 EJB 单例,因为我想要 EJB 的事务、线程安全等,因此仅将其保留为 @ApplicationScoped POJO 对我来说没有多大用处。不过,问题似乎并不局限于 Singleton beans - 我已经尝试将注释更改为 @Stateless 和 @Stateful,并且遇到了同样的问题。
在我看来,这可能是 Weld 中的一个错误,也许 Weld 和 EJB 正在争论如何代理该方法 - 大概 EJB 需要添加一个拦截器类并包装该方法以确保线程安全,而 Weld 正在尝试做一些事情要不然让事件监听器工作?
我是否误解了这里的某些内容,CDI 事件处理程序是否应该根本不用于 EJB(在这种情况下,glassfish 应该有更好的错误消息) - 或者这实际上只是 CDI 或 EJB 实现中的一个错误?
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 trying 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为这就是答案:
如果 EJB 声明了本地接口,CDI 观察者方法显然必须是静态的,或者在 EJB 的本地接口中声明。通常,如果您尝试声明不在本地接口中的观察者方法,您会从 Weld 收到如下异常:
由于某种原因,glassfish 在加载我的 EAR 文件时没有正确报告此异常,只是在加载时显示
Exception应用程序
。将方法添加到本地接口(或删除类上的接口声明)可以修复问题并允许应用程序正常加载。
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 :
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.
我注意到最新版本的焊接也存在同样的问题。但如果添加 @LocalBean 注释,它将与 @Singleton 和 @Singleton @Startup 一起使用。
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.