Managing JTA transaction in web client
sshort Jun 24, 2008 4:49 AMHello,
I am using JBoss 4.2.2GA and I would like to use a JTA based transaction within
a web client to span multiple stateless EJB session beans. Each stateless bean
uses a Hibernate EntityManager and is declared to use BMT. My understanding is
that this should work and the section titled "UserTransaction Support" of the
JBoss doc http://docs.jboss.org/admin-devel/Chap4.html supports this.
What I am finding is that the web client can lookup and begin a transaction, but
that the EJB does not see this transaction. I can see this by checking the
transaction status within the EJB itself.
Here is a simplified example based on the JBoss 'registration' example
application. This is the servlet code:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
UserTransaction tx = null;
try {
InitialContext ctx = new InitialContext();
SimpleUserManagement userManagement = (SimpleUserManagement) ctx.lookup("TestApplication/SimpleUserManagement/local");
tx = (UserTransaction)new InitialContext().lookup("UserTransaction");
String username = request.getParameter("username");
String name = request.getParameter("name");
String password = request.getParameter("password");
User user = new User(name, password, username);
log.info("Before tx.begin, transaction status = " + getTransactionStatusString(tx.getStatus()));
tx.begin();
log.info("Before saveUser, transaction status = " + getTransactionStatusString(tx.getStatus()));
userManagement.saveUser(user);
log.info("Before tx.commit, transaction status = " + getTransactionStatusString(tx.getStatus()));
tx.commit();
} catch (Exception ex) {
if (tx != null) {
try {
int status = tx.getStatus();
if (JTAHelper.isInProgress(status)) {
tx.rollback();
}
}
catch (Exception e) {
log.warn("Failed to rollback user update", e);
}
}
log.error("User update failed", ex);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "User management services are not currently available");
return;
}
}
And this is the EJB code:
public void saveUser(final User user) {
UserTransaction tx = null;
try {
tx = sessionContext.getUserTransaction();
if (JTAHelper.isInProgress(TransactionHelper.getTransactionStatus(tx))) {
log.info("A transaction is already in progress");
log.info("Before em.persist, transaction status = " + getTransactionStatusString(tx.getStatus()));
em.persist(user);
} else {
log.info("A transaction is NOT in progress");
log.info("Before tx.begin, transaction status = " + getTransactionStatusString(tx.getStatus()));
tx.begin();
log.info("Before em.persist, transaction status = " + getTransactionStatusString(tx.getStatus()));
em.persist(user);
log.info("Before tx.commit, transaction status = " + getTransactionStatusString(tx.getStatus()));
tx.commit();
}
}
catch (Exception ex) {
log.error("Failed to modify user", ex);
}
}
And this is the resulting log output showing that the EJB does not see that
the servlet has started a transaction:
[SimpleServlet] Before tx.begin, transaction status = NO_TRANSACTION [SimpleServlet] Before saveUser, transaction status = ACTIVE [SimpleUserManagementBean] A transaction is NOT in progress [SimpleUserManagementBean] Before tx.begin, transaction status = NO_TRANSACTION [SimpleUserManagementBean] Before em.persist, transaction status = ACTIVE [SimpleUserManagementBean] Before tx.commit, transaction status = ACTIVE [SimpleServlet] Before tx.commit, transaction status = ACTIVE
Regards
Steve