11 Replies Latest reply on Jun 18, 2007 11:41 AM by Gavin King

    Help with MDB + Seam + jBPM - transaction issue?

    Bradley Smith Master

      Hello,

      I have an MDB that invokes a SLSB method - the method does some persistence work and signals a jBPM ProcessInstance. I am consistently getting an exception related to transactions from jBPM. Here are the classes being used:

      The MDB:

      @MessageDriven(activationConfig = {
      @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:/SonicJMS/Queues/AccessControl/Receive"),
      @ActivationConfigProperty(propertyName = "providerAdapterJNDI", propertyValue = "java:/SonicJMSProvider"),
      @ActivationConfigProperty(propertyName = "useDLQ", propertyValue = "false")
       }
      )
      @Name("accessControlReceiveMDB")
      public class AccessControlReceiveMDB implements MessageListener {
      
       private Log log = LogFactory.getLog(AccessControlReceiveMDB.class);
      
       @EJB(beanName = "ProvisionSuccessBean")
       private ProvisionSuccess successfulResponse;
      
       @EJB(beanName = "ProvisionFailureBean")
       private ProvisionFailure failedResponse;
      
       @Resource
       MessageDrivenContext context;
      
       //@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
       public void onMessage(javax.jms.Message message) {
       log.info("AccessControlReceiveMDB : onMessage()");
       log.info(message);
       try {
       // Grab Message Type from header.
       MessageTypes messageType = null;
       try {
       messageType = MessageTypes.valueOf(message
       .getStringProperty(MessageHeaderKeys.MessageType
       .toString()));
       } catch (Exception e) {
       messageType = MessageTypes.UnknownMessageType;
       }
      
       Long processId = null;
      
       switch (messageType) {
       case ProvisionSuccess:
       // Grab process id from header.
       try {
       processId = Long.valueOf(message.getStringProperty(MessageHeaderKeys.ProcessId.toString()));
       log.info("processId -> "+processId);
       Contexts.getEventContext().set("processId",processId);
       if (successfulResponse == null) {
       log.error("successResponse bean is null.");
       }
       successfulResponse.confirmProvisioning();
       } catch (Exception e) {
       log.error(e,e);
       log.error(
       "\nMissing Process ID in message header for message "
       + message.getJMSMessageID()
       +".\nMessage will be consumed but no processing will occur.\n"
       );
       }
       break;
      
       case ProvisionFailure:
       // Grab process id from header.
       try {
       processId = Long.valueOf(message.getStringProperty(MessageHeaderKeys.ProcessId.toString()));
       } catch (Exception e) {
       throw new Exception("Missing Process Id in Message Header. " + e);
       }
      
       failedResponse.confirmProvisioning(
       processId,
       message.getStringProperty(MessageHeaderKeys.ProvisionException.toString())
       );
       break;
      
       case ActiveUserList:
       break;
      
       case ActiveUserListCSV:
       break;
      
       case UnknownMessageType:
       log.info("Discarding message of type '"+messageType+"' - unknown message type.");
       break;
      
       }
       } catch (JMSException jmse) {
       log.error("Allowed MessageTypes -> " + Arrays.asList(MessageTypes.values()));
       log.error(jmse, jmse);
       context.setRollbackOnly();
       } catch (Exception e) {
       log.error(e, e);
       context.setRollbackOnly();
       }
       }
      }
      


      The SLSB:
      @Stateless
      @Name("provisionSuccess")
      public class ProvisionSuccessBean implements ProvisionSuccess {
      
       //@Logger
       //protected Log log;
       private Log log = LogFactory.getLog(ProvisionSuccessBean.class);
      
       @PersistenceContext(unitName = "accessControlDatabase")
       protected EntityManager em;
      
       @In(create = true)
       private JbpmContext jbpmContext;
      
       public String confirmProvisioning(Long processId) {
       log.info("confirmProvisioning: " + processId);
      
       log.info("injected jbpmConext -> " + jbpmContext);
      
       ProcessInstance process = jbpmContext.getProcessInstance(processId);
       Long accessRequestId = (Long) process.getContextInstance().getVariable("accessRequestId");
      
       log.info("Access Request Id: " + accessRequestId);
       AccessRequest accessRequest = em.find(AccessRequest.class,accessRequestId.longValue());
       log.info("AccessRequest: " + accessRequest);
      
       .... A LOT OF BUSINESS LOGIC CUTOUT FROM HERE ....
       // Update the Access Request Decisions to include a complete decision.
       // Update the status of the Access Request to complete
       AccessRequestDecision decision = accessRequest.getDistributedSecurityAdminDecision();
       decision.setDecision(AccessRequestStatus.Complete);
       accessRequest.setRequestStatus(AccessRequestStatus.Complete);
       em.merge(decision);
       em.merge(accessRequest);
      
       // Signal to jBPM to move the workflow along
       log.info("Signaling workflow -> ProvisionSuccess");
      
       process.signal("ProvisionSuccess");
       jbpmContext.save(process);
      
       return "success";
       }
      
      }
      
      


      The exception as seen in the JBoss console:

      09:23:10,158 ERROR [StdServerSession] failed to commit/rollback
      org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=DEIBKST-6KZFT61/14, BranchQual=, localId=14] status=STATUS_NO_TRANSACTION; - nested throwable:
      (java.lang.NullPointerException)
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:372)
       at org.jboss.tm.TxManager.commit(TxManager.java:240)
       at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:351)
       at progress.message.jimpl.Session.dU_(Unknown Source)
       at progress.message.jimpl.Session.run(Unknown Source)
       at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:196)
       at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
       at java.lang.Thread.run(Thread.java:595)
      Caused by: java.lang.NullPointerException
       at org.jboss.seam.core.ManagedJbpmContext.beforeCompletion(ManagedJbpmContext.java:94)
       at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491)
       at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110)
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
       ... 7 more
      
      


      I think the following log statements from server.log show jBPM actually getting a handle to the UserTransaction:

      2007-02-08 09:23:10,111 DEBUG [org.jbpm.persistence.db.DbPersistenceServiceFactory] creating persistence service
      2007-02-08 09:23:10,111 DEBUG [org.jbpm.persistence.db.DbPersistenceService] creating hibernate session
      2007-02-08 09:23:10,111 DEBUG [org.hibernate.impl.SessionImpl] opened session at timestamp: 4796189041094656
      2007-02-08 09:23:10,127 DEBUG [org.hibernate.transaction.JTATransaction] Looking for UserTransaction under: UserTransaction
      2007-02-08 09:23:10,127 DEBUG [org.hibernate.transaction.JTATransaction] Obtained UserTransaction
      2007-02-08 09:23:10,127 DEBUG [org.jboss.mx.loading.RepositoryClassLoader] setRepository, repository=org.jboss.mx.loading.HeirarchicalLoaderRepository3@40a1e1, cl=org.jboss.mx.loading.HeirarchicalLoaderRepository3$CacheClassLoader@d3e5cc{ url=null ,addedOrder=0}
      2007-02-08 09:23:10,127 DEBUG [org.jboss.seam.interceptors.BijectionInterceptor] disinjecting dependencies of: provisionSuccess
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
      


      and here we see Seam tearing down the jBPM Context and the transaction exception occuring from the server.log:

      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.core.ManagedJbpmContext] destroying seam managed jBPM context
      2007-02-08 09:23:10,142 DEBUG [org.jbpm.JbpmContext] closing JbpmContext
      2007-02-08 09:23:10,142 DEBUG [org.jbpm.svc.Services] closing service 'persistence': org.jbpm.persistence.db.DbPersistenceService@1c4f6f6
      2007-02-08 09:23:10,142 DEBUG [org.jbpm.persistence.db.DbPersistenceService] flushing hibernate session
      2007-02-08 09:23:10,142 DEBUG [org.hibernate.jdbc.JDBCContext] successfully registered Synchronization
      2007-02-08 09:23:10,142 DEBUG [org.jbpm.persistence.db.DbPersistenceService] closing hibernate session
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.core.ManagedJbpmContext] done destroying seam managed jBPM context
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
      2007-02-08 09:23:10,142 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postDestroyContext.EVENT
      2007-02-08 09:23:10,158 DEBUG [org.jboss.seam.contexts.Lifecycle] <<< End call
      2007-02-08 09:23:10,158 DEBUG [org.jboss.seam.core.ManagedJbpmContext] flushing seam managed jBPM context
      2007-02-08 09:23:10,158 DEBUG [org.jboss.util.NestedThrowable] org.jboss.util.NestedThrowable.parentTraceEnabled=true
      2007-02-08 09:23:10,158 DEBUG [org.jboss.util.NestedThrowable] org.jboss.util.NestedThrowable.nestedTraceEnabled=false
      2007-02-08 09:23:10,158 DEBUG [org.jboss.util.NestedThrowable] org.jboss.util.NestedThrowable.detectDuplicateNesting=true
      2007-02-08 09:23:10,158 ERROR [org.jboss.jms.asf.StdServerSession] failed to commit/rollback
      org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=DEIBKST-6KZFT61/14, BranchQual=, localId=14] status=STATUS_NO_TRANSACTION; - nested throwable: (java.lang.NullPointerException)
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:372)
       at org.jboss.tm.TxManager.commit(TxManager.java:240)
       at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:351)
       at progress.message.jimpl.Session.dU_(Unknown Source)
       at progress.message.jimpl.Session.run(Unknown Source)
       at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:196)
       at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
       at java.lang.Thread.run(Thread.java:595)
      Caused by: java.lang.NullPointerException
       at org.jboss.seam.core.ManagedJbpmContext.beforeCompletion(ManagedJbpmContext.java:94)
       at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491)
       at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110)
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
       ... 7 more
      


      Any help on this is appreciated.

      Thanks,
      Brad Smith