使用 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 中?