1

使用 CMT 的这种情况是有效的:

  • 带有 CMT 的无状态会话 bean,一种用@TransactionAttribute(TransactionAttributeType.MANDATORY). 在此方法中,使用 XA 数据源和普通 JDBC 将记录写入 RDBMS。

  • 独立客户端(单独的 JVM,命令行 Java 应用程序)UserTransaction从应用程序服务器(通过 JNDI 查找)获取一个,启动事务,并调用 EJB。

  • 如果客户端提交UserTransaction,则将记录写入数据库。

  • 如果客户端回滚UserTransaction,则记录不会写入数据库。
  • 在 PostgreSql 日志文件中,可以看到带有 BEGIN 和 COMMIT 或 ROLLBACK 的准备好的事务

  • 如果客户端在调用 EJB 之前没有启动事务,javax.ejb.EJBTransactionRequiredException则会抛出 a(如预期的那样TransactionAttributeType.MANDATORY)。

现在我从 CMT 切换到 BMT

  • 同样,如果客户端在调用 EJB 之前没有启动事务,javax.ejb.EJBTransactionRequiredException则会抛出 a(如预期的那样,TransactionAttributeType.MANDATORY)。

  • 如果我打电话sessionContext.getUserTransaction().getStatus(),它总是报告Status.STATUS_NO_TRANSACTION

  • commit如果客户端调用或,记录总是写入数据库rollback

  • 在 PostgreSql 日志文件中,没有准备好的事务,只是简单的插入命令。

EJB的来源:

@Remote(DemoIfc.class)
@Stateless(name = "DemoBmt")
@TransactionManagement(TransactionManagementType.BEAN)
public class DemoBmt implements DemoIfc {
    @Resource
    private SessionContext sessionContext;

    @TransactionAttribute(TransactionAttributeType.MANDATORY)
    public String ping(final String s) throws SystemException {
        try {
            System.out.println("TX: status: "
                    + this.sessionContext.getUserTransaction().getStatus());
        } catch (Exception e) {
            System.out.println("TX: status: " + e.getMessage());
        }

        try {
            writeIntoDb();
            if (s.startsWith("crash")) {
                throw new SystemException("Simulated crash");
            }
            return s.toUpperCase();
        } catch (NamingException e) {
            throw new SystemException(e.getMessage());
        } catch (SQLException e) {
            throw new SystemException(e.getMessage());
        }
    }
}

客户来源:

final UserTransaction ut = (UserTransaction) initialContext
        .lookup("UserTransaction");
try {
    ut.begin();
    System.out.println(demo.ping("crash: DemoBmt with UT"));
    ut.commit();
} catch (Exception ex) {
    System.out.println("Expected rollback");
    ut.rollback();
}

我正在使用 JBoss 6.0.0 最终版。

如何使用 BMT 正确地将客户端 UserTransaction 传播到 EJB 中?

4

1 回答 1

3

BMT bean 不能参与现有事务

EJB 3.1 规范:

13.6.1 Bean管理的事务划分

容器必须使用 bean 管理的事务划分来管理对企业 bean 实例的客户端调用,如下所示。当客户端通过企业 bean 的客户端视图之一调用业务方法时,容器将挂起任何可能与客户端请求相关联的事务......

于 2013-07-27T00:47:45.763 回答