Help with MDB + Seam + jBPM - transaction issue?
bsmithjj Feb 8, 2007 9:48 AMHello,
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