【发布时间】:2017-07-20 12:25:20
【问题描述】:
如何在无状态会话 bean 中获知事务需要回滚? 例如,我有一个无状态 EJB,它正在使用一些业务数据更新 LuceneIndex。该方法在具有多个 EJB 调用的事务中调用。 当一些后来的 EJB 回滚事务时,我怎样才能知道这个问题,以便我能够回滚我已经编写的 LuceneIndex 条目?
【问题讨论】:
标签: jakarta-ee transactions ejb
如何在无状态会话 bean 中获知事务需要回滚? 例如,我有一个无状态 EJB,它正在使用一些业务数据更新 LuceneIndex。该方法在具有多个 EJB 调用的事务中调用。 当一些后来的 EJB 回滚事务时,我怎样才能知道这个问题,以便我能够回滚我已经编写的 LuceneIndex 条目?
【问题讨论】:
标签: jakarta-ee transactions ejb
您可以通过注入对当前 EJBContext 的引用然后查询它来做到这一点:
@Stateless
public class LuceneDriver {
@Resource
private EJBContext ejbContext;
public void performLuceneStuff(...) {
try {
...
// update lucene data
...
// update some business data
...
} catch (BusinessException e) {
if (ejbContext.getRollbackOnly()) {
// rollback lucene changes
}
}
}
...
}
【讨论】:
ejbContext.getRollbackOnly() 唯一不起作用的情况是另一个 EJB 启动了一个新事务。只有在您明确配置时才会启动新事务。
如果会话 EJB 不是事务性的,您将无法在发生故障时回滚。这是因为无状态会话 EJB 缺少状态信息。
解决此问题的一个解决方案是使用实现javax.ejb.SessionSynchronization 接口的@Stateful 会话bean。此界面允许您对回滚做出反应。
另一个解决方案是使用主事务通过 JPA 编写的自定义 EventLog 条目。使用这些 eventLog 条目,另一个无状态会话 EJB 可以验证是否存在新的 EventLog 条目以及是否可以对其做出反应。如果事务被回滚,事务管理器也将删除未提交的 EventLog 条目。因此,这是一种将非事务性功能耦合到基于 JPA 容器的事务的解决方案。看问题:How to react on a EJB3 transaction commit or rolleback?
【讨论】: