在事务中进行无事务EJB调用

时间:2009-09-04 19:57:30

标签: java java-ee transactions ejb jta

我会试着描述一下情况。我们有网络服务;在每个请求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();

3 个答案:

答案 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();
    }
}