3

我有两个 SLSB:

  • BeanF,
  • BeanO

在两个 ejb-jar 中:

  • ModF,
  • ModO.

BeanF触发一个事件并BeanO观察它。

第一个fire(-)操作以异常结束(Wildfly 8.2):

错误 [org.jboss.as.ejb3.invocation] JBAS014134:组件 BeanF 上的 EJB 调用失败,用于方法 public void BeanF.publish(ModEvent):
javax.ejb.EJBException:org.jboss.msc.service.ServiceNotFoundException:服务服务
jboss .deployment.subunit."myapp.ear"."modO.jar".component.BeanO.VIEW."BeanO".LOCAL 未找到

进一步fire(-)的操作到达观察者,但我不能让任何事件丢失。

有没有办法在事件被触发之前强制初始化观察者(或者在事件被触发并等待处理之后)?

@Observes(notifyObserver = Reception.IF_EXISTS)唯一允许在观察者尚未准备好时静默跳过事件。
在我的情况下,BeanF不能依赖,BeanO因为ModO必须ModFapplication.xml.

是否可以使用 CDI 事件/侦听器,或者我需要使用 JMS?

4

2 回答 2

3

其他实验

尝试使用 and 注释两个 bean@Singleton@Startup收到相同的异常(我无法注释BeanF@DependsOn( BeanO )因为ModF没有看到ModO)。还尝试更改BeanO@ApplicationScoped,在这种情况下可以接收事件-该BeanO.observe(@Observes ...)方法开始执行,执行了一些日志记录,但ServiceNotFoundException在尝试调用其他@Statelessbean 时因异常而崩溃(这个其他 bean 必须是@Stateless因为它使用TransactionAttributeType.REQUIRES_NEW注释)。

CDI 解决方案

有点难看但可行的解决方案:缓存/排队事件:分成BeanO两个 bean:BeanO1BeanO2. 让我们BeanO1成为一个@ApplicationScopedbean,让它观察事件并BeanO2通过调用一些空心方法和捕获来检测是否准备好ServiceNotFoundException。如果BeanO2不存在,则事件将在ConcurrentLinkedQueue中排队BeanO1。是无状态的,除了观察之外BeanO2,什么都做。BeanO当事件到达并BeanO2准备好时,BeanO1首先从队列中推送事件。只有当有一些其他事件会实际触发处理较旧的事件时,这才是可接受的。

管理系统

我想使用 JMS 将是最干净的解决方案,但也有一些陷阱:

  • 如果topic使用 a ,那么我们可能会再次陷入最初的问题 - 订阅者在发送第一条消息后注册(不确定规范,但当没有订阅者时消息会丢失)。
  • 如果使用 a ,则在其他产品中使用queue时可能会出现问题ModF并且没有ModO- 队列会膨胀,这可能不是超级直觉。
    • 也许ModF可以定义一些MDB读取所有事件的事件丢弃它们并ModO以某种方式注册具有更高优先级的自己的MDB(只是猜测,不知道这是否可能)
    • 也许ModO可以包含带有队列名称的配置文本文件,因此ModF可以读取该文件,即时初始化与队列的连接并将事件放入该队列(如果没有ModO并且没有文件,则不会触发事件ModF)。
于 2015-04-09T09:21:36.307 回答
1

首先,我认为 CDI 创建了一个 bean 的“新”实例并将事件传递给它以防万一

  • 没有活动的上下文实例(在当前范围内),并且
  • 观察者不是有条件的

我在这里写了这个

所以这种行为很奇怪IMO

在替代方案方面 - 是否可以将您的观察者方法声明为“静态”?在这种情况下,CDI 肯定会调用它

另外,如果您还没有,我强烈建议您阅读 CDI 规范文档(第 10 章和第 5.5.6 节)

于 2015-04-09T03:05:23.660 回答