我在负责启动事务的 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 中的默认值)。
为什么我会收到“交易未激活”?
非常感谢,
亚尼夫
最佳答案
问题是您启动的原始事务仍然与该线程关联(即使它处于 COMMITTED 状态)。使用 Transaction 之间的显着差异之一和 TransactionManager是后者的commit()和 rollback()方法将取消事务与线程的关联。引用这两种方法的 javadoc:
When this method completes, the thread is no longer associated with a transaction.
有两种方法可以解决这个问题(我以一种非常原始的方式概述了它们,您可能需要稍微改进一下)。
选项 1:针对事务管理器发出回滚或提交(在 try block 中,因为它会失败)。
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 容器启动新事务。
关于java - 事务未激活异常 - EJB 事务状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9069518/