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