Reputation: 12998
This scenario using CMT is working:
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.
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.
If the client commits the UserTransaction
, the record is written into the database.
UserTransaction
, the record is not written into the database.In the PostgreSql log files, one can see the prepared transaction with BEGIN, and COMMIT or ROLLBACK
If the client does not start a transaction before calling the EJB, a javax.ejb.EJBTransactionRequiredException
is thrown (as expected, TransactionAttributeType.MANDATORY
).
Now I switch from CMT to BMT
Again, if the client does not start a transaction before calling the EJB, a javax.ejb.EJBTransactionRequiredException
is thrown (as expected, TransactionAttributeType.MANDATORY).
If I call sessionContext.getUserTransaction().getStatus()
, it always reports Status.STATUS_NO_TRANSACTION
.
The record is always written into the database, if the client calls commit
or rollback
.
In the PostgreSql log files, there are no prepared transactions, just plain insert commands.
The source of the 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());
}
}
}
The client's source:
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();
}
I am using JBoss 6.0.0 final.
How can I properly propagate the client-side UserTransaction into the EJB with BMT?
Upvotes: 1
Views: 2350
Reputation: 2981
BMT beans cannot participate in an existing transaction
From EJB 3.1 spec.:
13.6.1 Bean-Managed Transaction Demarcation
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....
Upvotes: 3