2 Replies Latest reply on Aug 13, 2007 10:37 AM by wolfc

    Transaction is not active after rollback

      The issue is that I have a stateless EJB using CMT with the following problem:
      a function X, having default transaction attribute (required) has a loop and calls another function Y with a transaction attribute of REQUIRES_NEW. Function Y does a SessionContext.setRollbackOnly. First itration calls Function Y, does rollback and exits. Second iteration of loop, function Y is called and I get the following; the error occurs during the getConnection() call in the JBPMDao.removeEndedProcesses(pidVec) function (see below)


      org.jboss.util.NestedSQLException: Transaction is not active: tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=ro-0029aits/49, BranchQual=, localId=49]; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=ro-0029aits/49, BranchQual=, localId=49])



      Here is the code
      /**
       * Method: cleanupEndedProcesses
       * Purpose: Called from a servlet to cleanup runtime data for ended processinstances
       * @param processId
       */
       public void cleanupEndedProcesses(String processId)
       {
      
       JbpmDAO jbpmDAO = null;
       Vector<String> pidVec = new Vector<String>();
       List<String> tmpList;
       int cnt = 0;
       int BATCHSIZE = 500;
       int endNdx = 0;
      
       try {
       logger.debug("cleanupEndedProcesses:: start");
       jbpmDAO = new JbpmDAO();
       pidVec = jbpmDAO.getEndedProcesses(processId);
       while (pidVec.size() > 0)
       {
       endNdx = pidVec.size() > BATCHSIZE? BATCHSIZE:pidVec.size();
       tmpList = new ArrayList<String>(pidVec.subList(0, endNdx));
       batchRemoveEndedProcesses(tmpList, jbpmDAO);
       cnt += endNdx;
       pidVec.removeAll(tmpList);
       }
       }
       catch (Exception e) {
       throw new WorkflowException(e);
       }
       logger.debug("cleanupEndedProcesses:: pids removed = " + cnt);
      
       }
      
      
       /**
       * Method: batchRemoveEndedProcesses
       * Purpose: separated out so that we could batch deletes
       * @param pidVec
       * @param jbpmDAO
       */
       @TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
       private void batchRemoveEndedProcesses(List<String> pidVec, JbpmDAO jbpmDAO)
       {
       try {
       jbpmDAO.removeEndedProcesses(pidVec);
       context.setRollbackOnly();
       }
       catch (Exception e) {
       throw new WorkflowException(e);
       }
       }
      


      public void removeEndedProcesses(List<String> pidVec)
       {
       String strQuery = DELETE_JBPM_PROCESSINSTANCES;
       Connection con = null;
       PreparedStatement pstmt = null;
      
       try {
       con = getJbpmDataSource().getConnection();
       String strInClause = constructInClause(pidVec);
       strQuery = strQuery.replaceAll(":list", strInClause);
       pstmt = con.prepareStatement(strQuery);
       bindVarsToInClause(pidVec, 1, pstmt);
       pstmt.executeUpdate();
       }
       catch (SQLException e) {
       throw new LoggableEJBException(e);
       }
       finally {
       try {
       if (pstmt != null)
       pstmt.close();
       if (con != null)
       con.close();
       }
       catch (SQLException e) {
       throw new LoggableEJBException(e);
       }
       }
      
       }
      


        • 1. Re: Transaction is not active after rollback
          jc7442

          When an exception is thrown in a session bean, container rollback the transaction. You can change that using the ApplicationException annotation in your Excpetion code. This annotation has an attribute rollback:

          @ApplicationException(rollback=false)
          public class AuditLockException extends AuditException {
          ...}


          • 2. Re: Transaction is not active after rollback
            wolfc

            A direct call doesn't look at any transaction or security attributes. You should call the method through the business interface:

            context.getBusinessObject(MyStateless.class).batchRemoveEndedProcesses(tmpList, jbpmDAO);

            Make sure it's a local interface or you'll run into trouble with the jbpmDAO references.