我会试着描述一下情况。我们有网络服务;在每个请求Web服务启动JTA事务。它通过其中的XA数据源执行多个数据库调用,并调用其他一些Web服务(在事务上下文之外),并在其他服务器上进行一些远程EJB调用。
问题是容器似乎试图让EJB进入事务(这似乎是合乎逻辑的),但实际上我希望它不参与该事务,因为当它参与该事务时它总是在最后一次超时提交阶段,但是当我排除EJB调用时它工作正常。
我无法更改EJB实现,只能控制Web服务代码。所以,我的问题是:如何对事务感知EJB进行EJB调用,但是在我的JTA事务之外,但仍然在JTA事务中用于其他XA资源?我希望我明白我的问题:)。
编辑:尝试使用伪代码示例更清晰:
// Begin transaction
UserTransaction tx = (UserTransaction) ctx.lookup(USER_TRANSACTION);
tx.begin();
// Do some database operations on XA datasource
// Call remote EJB which has transcation attribute set to 'Supports'
AccountInfo account = accountEjb.getAccountInfo(userId, accountId); // <-- Is it possible to make this to be not be part of user transction?
// Do some more database operations on XA datasource
// Commit transaction
tx.commit();
答案 0 :(得分:3)
您可以使用一些适当的事务属性创建另一个bean。这个bean可以将所有调用委托给第一个bean。
或者你可以从另一个线程调用这个ejb。
答案 1 :(得分:1)
EJB事务是声明性的:对于给定EJB的给定部署,您可以指定其事务语义。可以部署确切的EJB(当然,使用不同的名称),您可以为该部署指定不同的要求。这假设(a)你至少拥有ejb的jar,并且(b)所讨论的ejb是独立的并且不依赖于其他组件,并且(c)ejb的开发者没有在违反事务上下文的情况下,它违反了声明式事务和他的bean工作的想法。
答案 2 :(得分:0)
您可以使用合适的tx属性创建另一个方法,然后通过自注代理代理(伪代码)调用它:
@Stateless
public class LocalEJB1 {
@EJB
private LocalEJB1 localEJB1;
@EJB
private AccountEJB accountEjb;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public AccountInfo callNonTx() {
return accountEjb.getAccountInfo(userId, accountId);
}
public void yourCurrentMethod() {
// Begin transaction
UserTransaction tx = (UserTransaction) ctx.lookup(USER_TRANSACTION);
tx.begin();
AccountInfo account = localEJB1.callNonTx();
// Do some more database operations on XA datasource
// Commit transaction
tx.commit();
}
}