如何使用 BMT 将客户端 UserTransaction 传播到无状态会话 bean [英] How to propagate a client-side UserTransaction into a stateless session bean using BMT
问题描述
这个使用 CMT 的场景有效:
This scenario using CMT is working:
带有 CMT 的无状态会话 bean,一种用
@TransactionAttribute(TransactionAttributeType.MANDATORY)
注释的方法.在此方法中,使用 XA 数据源和普通 JDBC 将记录写入 RDBMS.
Stateless session bean with CMT, one method annotated with
@TransactionAttribute(TransactionAttributeType.MANDATORY)
. Within this method, a record is written into a RDBMS using an XA data source and plain JDBC.
独立客户端(单独的 JVM,命令行 Java 应用程序)正在从应用程序服务器(通过 JNDI 查找)获取 UserTransaction
,启动事务,并调用 EJB.
The stand-alone client (separate JVM, command-line Java application) is getting a UserTransaction
from the application server (by JNDI lookup),
starts the transaction, and calls the EJB.
如果客户端提交了UserTransaction
,记录被写入数据库.
If the client commits the UserTransaction
, the record is written into the database.
在 PostgreSql 日志文件中,可以看到准备好的事务带有 BEGIN、COMMIT 或 ROLLBACK
In the PostgreSql log files, one can see the prepared transaction with BEGIN, and COMMIT or ROLLBACK
如果客户端在调用 EJB 之前没有启动事务,则会抛出 javax.ejb.EJBTransactionRequiredException
(正如预期的那样,TransactionAttributeType.MANDATORY
).
If the client does not start a transaction before calling the EJB, a javax.ejb.EJBTransactionRequiredException
is thrown (as expected, TransactionAttributeType.MANDATORY
).
现在我从 CMT 切换到 BMT
Now I switch from CMT to BMT
同样,如果客户端在调用 EJB 之前没有启动事务,则会抛出
javax.ejb.EJBTransactionRequiredException
(正如预期的那样,TransactionAttributeType.MANDATORY).
Again, if the client does not start a transaction before calling the EJB, a
javax.ejb.EJBTransactionRequiredException
is thrown (as expected, TransactionAttributeType.MANDATORY).
如果我调用 sessionContext.getUserTransaction().getStatus()
,它总是报告 Status.STATUS_NO_TRANSACTION
.
If I call sessionContext.getUserTransaction().getStatus()
, it always reports Status.STATUS_NO_TRANSACTION
.
记录总是写入数据库,如果客户端调用commit
或rollback
.
The record is always written into the database, if the client calls commit
or rollback
.
在 PostgreSql 日志文件中,没有准备好的事务,只有简单的插入命令.
In the PostgreSql log files, there are no prepared transactions, just plain insert commands.
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 final.
I am using JBoss 6.0.0 final.
如何使用 BMT 将客户端 UserTransaction 正确传播到 EJB 中?
How can I properly propagate the client-side UserTransaction into the EJB with BMT?
推荐答案
BMT bean 不能参与现有事务
BMT beans cannot participate in an existing transaction
来自 EJB 3.1 规范:
13.6.1 Bean 管理的事务划分
13.6.1 Bean-Managed Transaction Demarcation
容器必须管理客户对企业 bean 的调用具有 bean 管理的事务划分的实例如下.当一个客户端通过企业 bean 的其中一个调用业务方法客户端视图,容器暂停任何可能发生的事务与客户端请求相关联....
The container must manage client invocations to an enterprise bean instance with bean-managed transaction demarcation as follows. When a client invokes a business method via one of the enterprise bean’s client views, the container suspends any transaction that may be associated with the client request....
这篇关于如何使用 BMT 将客户端 UserTransaction 传播到无状态会话 bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!