【问题标题】:How making stateless session beans transaction-aware?如何使无状态会话 bean 具有事务意识?
【发布时间】:2017-07-20 12:25:20
【问题描述】:

如何在无状态会话 bean 中获知事务需要回滚? 例如,我有一个无状态 EJB,它正在使用一些业务数据更新 LuceneIndex。该方法在具有多个 EJB 调用的事务中调用。 当一些后来的 EJB 回滚事务时,我怎样才能知道这个问题,以便我能够回滚我已经编写的 LuceneIndex 条目?

【问题讨论】:

    标签: jakarta-ee transactions ejb


    【解决方案1】:

    您可以通过注入对当前 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
                 }
             }
         }
    
         ...
    
    }
    

    【讨论】:

    • 但是如果在我的方法 performLuceneStuff() 已经完成后,回滚由同一事务中的另一个 EJB 初始化怎么办?
    • 没关系。 EJB 一直具有高度的事务意识。 ejbContext.getRollbackOnly() 唯一不起作用的情况是另一个 EJB 启动了一个新事务。只有在您明确配置时才会启动新事务。
    • 我可能仍然站在软管上......我期待的是一种注册回调方法的机制,当同一事务中的其他人(不是我的 bean)时,事务管理器会调用该回调方法失败的。这样我就可以撤消 - 我已经编写的索引文件。
    • 好吧,我慢慢认错了。由于缺少状态信息,无法调用无状态 EJB 进行回滚。也许我需要某种资源适配器来管理我的 Lucene 索引问题......
    • 如果您不介意管理生命周期,您可以使用实现javax.ejb.SessionSynchronization 接口的@Stateful bean。这提供了一个回调。您可以使用 EJB 的“状态”来提供回滚 Lucene 更改所需的信息
    【解决方案2】:

    如果会话 EJB 不是事务性的,您将无法在发生故障时回滚。这是因为无状态会话 EJB 缺少状态信息。

    解决此问题的一个解决方案是使用实现javax.ejb.SessionSynchronization 接口的@Stateful 会话bean。此界面允许您对回滚做出反应。

    另一个解决方案是使用主事务通过 JPA 编写的自定义 EventLog 条目。使用这些 eventLog 条目,另一个无状态会话 EJB 可以验证是否存在新的 EventLog 条目以及是否可以对其做出反应。如果事务被回滚,事务管理器也将删除未提交的 EventLog 条目。因此,这是一种将非事务性功能耦合到基于 JPA 容器的事务的解决方案。看问题:How to react on a EJB3 transaction commit or rolleback?

    【讨论】:

      猜你喜欢
      • 2014-04-06
      • 1970-01-01
      • 2013-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 2013-02-04
      相关资源
      最近更新 更多