事务不活动异常 - EJB事务状态

时间:2012-01-30 19:25:18

标签: java transactions jboss ejb transactionmanager

我遇到了负责启动事务的EJB组件的问题。 我正在使用Jboss 5.01。

基本上我想在提交特定事务后执行给定代码。特定代码还涉及调用EJB组件,使其成为自己的事务。

为了确保我的代码在提交上一个事务后执行,我已经注册了一个 将同步组件转换为事务组件:

Transaction tx = transactionManager.getTransaction();
tx.registerSynchronization(new CallbackSynchronization());

Synchronizaton实现基本上执行以下操作:

class CallbackSynchronization implements Synchnronization {

    private AccountService service;  // This is a Stateless session bean

    public CallbackSynchronization(AccountService service) {
        this.service   = service;
    }

    public afterCompletion(int status) {
        if(Status.STATUS_COMMITTED == status) {
            service.deleteAccounts();
        }
    }
}

问题是当我调用service.deleteAccounts()时,我得到一个异常,最终告诉我事务处于非活动状态。

这让我很困惑。标记为@TransactionAttribute(TransactionAttributeType.REQUIRED)的方法的EJB将创建一个新事务(如果一个未激活)(REQUIRED是JBOSS中的默认值)。

为什么我得到“交易不活跃”?

非常感谢,

参见Yaniv

1 个答案:

答案 0 :(得分:3)

问题是您启动的原始事务仍与该线程关联(即使它处于COMMITTED状态)。使用TransactionTransactionManager之间的一个显着差异是后者的commit()rollback()方法会将事务与线程取消关联。引用两种方法的javadoc:

  

此方法完成后,该线程不再与a关联   事务。

有两种方法可以解决这个问题(我会以一种非常原始的方式概述它们,您可能需要稍微改进一下)。

选项1:针对事务管理器发出回滚或提交(在try块中,因为它将失败)。

public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { transactionManager.rollback(); } catch (Throwable t) {}
    service.deleteAccounts();
  }
}

选项2:启动一个新事务,它通过预启动事务来满足EJB的REQUIRED属性,但是你需要坚持并管理它变得粘滞。

public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { 
      transactionManager.begin();
      service.deleteAccounts();
      transactionManager.commit();
    } catch (Exception e) {
        // ... handle exception here
    }
  }
}

选项3:最干净的选项可能是将EJB方法标记为 REQUIRES_NEW ,因为这会强制EJB容器启动新事务。