I have the requirement to start a process instance from a MessageDrivenBean. I.e. a message arrives and starts a process. A single message should start one and only one process instance. Message loss is not acceptable, neither are duplicate process instances.
To implement this, I configured jBPM5 to use JPA and JTA. The idea is to have a JTA Transaction span both the delivery of the JMS message, as well as the start of the process instance (until the first save-point). I'm running a StatefulKnowledgeSession (SKS) per Process Instance architecture, i.e. every process instance runs in its own SKS. According to the SKS API, one should call 'sks.dispose' when one is done with the SKS. This way, the SKS' resources are freed, the SKS is persisted to the DB and can be reloaded when it is needed again: http://docs.jboss.org/jbpm/v5.2/javadocs/org/drools/runtime/StatefulKnowledgeSession.html
When doing this, I encounter a problem with calling 'sks.dispose()' inside a transaction. As mentioned here: https://community.jboss.org/thread/201901 , you cannot call 'sks.dispose()' inside a transaction. The problem seems to be that the SKS registers a transaction synchronization callback, which is called after transaction completion. But because of the fix of https://issues.jboss.org/browse/JBRULES-1880 , calling any method on an SKS after it has been disposed will throw a IllegalStateException. As explained here, the 'sks.dispose()' method should be called outside of the transaction boundaries: https://community.jboss.org/thread/201901 This is also the solution implemented in the ProcessFlowProvision framework(i.e. it resorts to Bean Managed Transactions (BMT)): http://people.redhat.com/jbride/
The problem is that I can't call 'sks.dispose()' outside of the transaction boundary. In an MDB, the transactional boundaries are controlled by the JCA Inflow logic. I can't resort to BMT as that would cause the delivery (and acknowledgement) of the JMS message to be in a different transaction than the start of the process instance. This clearly does not implement the requirement outlined earlier as this could cause duplicate process instances being started (in certain situations, for example a crash after the process instance has been created, but before the JMS message has been ack'ed. When the message is re-delivered, a second process instance will be created). The current solution that I've implemented is to register my own Transaction Synchronization callback, which, after transaction completion, suspends the transaction, calls 'sks.dispose()' and resumes the transaction. This is custom logic which developers need to implement themselves, and frankly, it is not really obvious, every-day, Java 101 code.
It would be nice if one would be able to either dispose the SKS from within a JTA transaction, or if jBPM5 would provide an easy to use API that will do this for you, without having to resort to writing custom TransactionSynchronization callback logic.
This is a piece of the code I'm using now to get this to work (the 'tm' variable is the injected/looked up TransactionManager, 'utx' is the UserTransaction):