0 Replies Latest reply on Jun 24, 2008 4:49 AM by sshort

    Managing JTA transaction in web client

    sshort

      Hello,

      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