【发布时间】:2016-05-15 07:48:15
【问题描述】:
在 WildFly 8/10 上,我有一个简单的 SLSB 触发 CDI 事件:
@Stateless
@Remote(CDITestRemote.class)
@Local(CDITestLocal.class)
public class CDITestBean implements CDITestRemote, CDITestLocal {
@Inject
private Event<IVolumeEvent> events;
@Override
public String insert(final String value) {
final IVolumeEvent event = new VolumeEvent();
events.fire(event);
return String.format("value: %s", value);
}
}
还有一个@ApplicationScoped“CDI 事件观察者”,用于 EJB 触发的事件类型:
@ApplicationScoped
public class VolumeEventObserver {
private Logger logger = LoggerFactory.getLogger(VolumeEventObserver.class);
@Inject
private TransactionHandler txHandler;
public void inProgress(
@Observes(during = TransactionPhase.IN_PROGRESS) final IVolumeEvent event) {
logger.info("@Observes progress() {}", String.valueOf(txHandler));
}
public void afterSuccess(
@Observes(during = TransactionPhase.AFTER_SUCCESS) final IVolumeEvent event) {
logger.info("@Observes success() {}", String.valueOf(txHandler));
}
public void afterFailure(
@Observes(during = TransactionPhase.AFTER_FAILURE) final IVolumeEvent event) {
logger.info("@Observes failure() {}", String.valueOf(txHandler));
}
}
TransactionHandler 是 @RequestScoped CDI bean:
@RequestScoped
public class TransactionHandler {
// some methods here...
}
当我在注入 REST 资源的 EJB 实例上调用 insert() 时,在对 REST 端点的请求期间,我在 VolumeEventObserver 的任何观察者方法中看到相同的 TransactionHandler 实例预期:
11:23:58,476 INFO [VolumeEventObserver] (default task-11) @Observes progress() TransactionHandler@7687eead
11:23:58,479 INFO [VolumeEventObserver] (default task-11) @Observes success() TransactionHandler@7687eead
但是当我进行远程 EJB 调用时,我在同一请求中看到 不同 个实例:
11:42:01,461 INFO [VolumeEventObserver] (EJB default - 2) @Observes progress() TransactionHandler@2e65f10d
11:42:01,463 INFO [VolumeEventObserver] (EJB default - 2) @Observes success() TransactionHandler@2a5a7019
所以TransactionHandler 似乎不在请求范围内。
JSR-299 表示请求范围处于活动状态:
在任何 EJB 的任何远程方法调用期间,在任何 任何 EJB 的异步方法调用 [...]
而且由于没有ContextNotActiveException,我想请求范围是活动的 - 那么为什么我会得到不同的实例呢?
这是同一个线程(从日志条目可以看出),事务也是一样的。
【问题讨论】:
-
我不认为可以将 EJB 远程调用视为请求(嗯,至少在规范中),因此在此类调用期间使用 @RequestScoped bean 可能会产生危险的结果。
-
我不明白你的意思 - 如果规范和 WELD 参考说“请求和应用程序范围也处于活动状态:在调用 EJB 远程方法期间”那么我只期望 @RequestScoped bean工作。
-
你还有什么办法可以查出TransactionHandler是否相同?你可以在不同的对象上调用
String.value(),代理同一个TransactionHandler实例(因为它是@RequestScoped,你得到一个代理而不是注入的真实实例)。 -
好吧,我已经用 OpenEJB 测试了您的案例,并且得到了相同的 TransactionHandler 实例。也许这是wildfly的问题......
-
谢谢,很高兴知道它可以与 OpenEJB 一起按预期工作!对于您之前的评论 - 我添加了一个 UUID 字段并且值不同。
标签: jakarta-ee ejb cdi