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