我有两个SLSB:
BeanF
,BeanO
在两个ejb-jar中:
ModF
,ModO
。 BeanF
触发一个事件,BeanO
观察它。
第一个fire(-)
操作以异常(Wildfly 8.2)结束:
错误[org.jboss.as.ejb3.invocation] JBAS014134:对于方法public void BeanF.publish(ModEvent),组件BeanF上的EJB调用失败:
javax.ejb.EJBException:org.jboss.msc.service.ServiceNotFoundException:服务服务
jboss.deployment.subunit。“myapp.ear”。“modO.jar”.component.BeanO.VIEW。“BeanO”.LOCAL not found
进一步fire(-)
次操作到达观察者但我不能让任何事件丢失。
是否有办法在事件被触发之前强制的观察者初始化(或者在事件被触发并等待处理后动态执行)?
@Observes(notifyObserver = Reception.IF_EXISTS)
只允许在观察者尚未准备就绪时以静默方式跳过事件。
在我的情况下,BeanF
不能依赖BeanO
因为ModO
必须在ModF
application.xml
之后宣布。
是否可以使用CDI事件/监听器,还是需要使用JMS?
答案 0 :(得分:3)
尝试使用@Singleton
和@Startup
注释两个bean并收到相同的异常(我无法使用BeanF
注释@DependsOn( BeanO )
因为ModF
没有看到{{} 1}})。
还尝试将ModO
更改为BeanO
,在这种情况下可以接收事件 - @ApplicationScoped
方法已开始执行,执行了一些日志记录但在尝试调用时因BeanO.observe(@Observes ...)
异常而崩溃其他一些ServiceNotFoundException
bean(另一个bean必须是@Stateless
,因为它使用@Stateless
注释。
有点难看但有效的解决方案:缓存/排队事件:将TransactionAttributeType.REQUIRES_NEW
拆分为两个bean:BeanO
和BeanO1
。让BeanO2
成为BeanO1
bean,让它观察事件并通过调用一些空洞方法并捕获@ApplicationScoped
来检测BeanO2
是否准备就绪。如果ServiceNotFoundException
不存在,那么该事件将在BeanO2
ConcurrentLinkedQueue
中排队。 BeanO1
是无国籍的,除了观察之外,做BeanO2
正在做的所有事情。当事件到达并且BeanO
准备就绪时,BeanO2
首先从队列中推送事件。只有在将成为实际触发处理旧事件的其他事件时才可以接受。
我想使用JMS将是最干净的解决方案,但也有一些陷阱:
BeanO1
,那么我们可能会再次陷入原始问题 - 用户在发送第一条消息后进行注册(不确定规范,但是当没有订户时消息会丢失)。 topic
,则在某些其他产品中使用queue
并且没有ModF
时可能会出现问题 - 队列会膨胀,这可能不是超级肠道。
ModO
可以定义一些ModF
读取所有事件丢弃它们,MDB
以某种方式注册自己的ModO
具有更高优先级(只是猜测,不知道)如果可能的话)MDB
可以包含具有队列名称的配置文本文件,因此ModO
可以读取该文件,动态初始化与队列的连接并将事件放入此队列(如果没有{{ 1}}并且没有文件,然后ModF
)不会触发事件。答案 1 :(得分:1)
首先,我认为CDI创建了一个bean的“新”实例并将事件传递给它
我写了这篇here
所以这种行为很奇怪IMO
就替代方案而言 - 是否可以将观察者方法声明为“静态”? CDI肯定会在那种情况下调用它
另外,如果您还没有,我强烈建议您阅读CDI规范文档(第10章和第5.5.6节)