Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 事务未激活异常-EJB事务状态_Java_Transactions_Jboss_Ejb_Transactionmanager - Fatal编程技术网

Java 事务未激活异常-EJB事务状态

Java 事务未激活异常-EJB事务状态,java,transactions,jboss,ejb,transactionmanager,Java,Transactions,Jboss,Ejb,Transactionmanager,我对负责启动事务的EJB组件有问题。 我正在使用JBoss5.01 基本上,我希望在提交特定事务后执行给定的代码。特定代码还涉及调用EJB组件,该组件生成自己的事务 为了确保在提交上一个事务后执行我的代码,我注册了 将同步组件转换为事务组件: Transaction tx = transactionManager.getTransaction(); tx.registerSynchronization(new CallbackSynchronization()); Synchronizaton

我对负责启动事务的EJB组件有问题。 我正在使用JBoss5.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();
        }
    }
}
问题是,当我调用
服务.deleteAccounts()
时,我得到一个异常,它最终会告诉我事务未激活

这就是让我困惑的地方。带有标记为
@TransactionAttribute(TransactionAttributeType.REQUIRED)
的方法的EJB将创建一个新事务,如果一个事务未处于活动状态(REQUIRED是JBOSS中的默认值)

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

非常感谢,


Yaniv

问题在于,您启动的原始事务仍然与线程关联(即使它处于已提交状态)。使用和之间的一个显著区别是,后者的和方法将使事务与线程解除关联。引用javadoc中的两种方法:

当此方法完成时,线程不再与 交易

有两种方法可以解决这个问题(我以一种非常原始的方式概述了它们,您可能希望对其进行一些改进)

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

选项2:启动一个新的事务,它将通过预启动事务来满足EJB的必需属性,但是您需要坚持并管理它,这会变得很棘手

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\u NEW,因为这将强制EJB容器启动新事务。

感谢Nicholas,为了使事情更干净,我决定发送一条JMS消息,它将触发下一个EJB调用。
public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { 
      transactionManager.begin();
      service.deleteAccounts();
      transactionManager.commit();
    } catch (Exception e) {
        // ... handle exception here
    }
  }
}