I'm afraid this bug is not resolved and doesn't have nothing to do with
lazy evaluation.
We've been able to get to the source of the problem and this are the facts:
- Drools and JBPM have different persistence managers.
- Drools uses JTA for persistence and JBPM does not.
- When any JPA enabled object is persisted in Drools, a transaction
begins, it's EntityManager ( Hibernate ) joins the transaction and the
entity gets persisted.
- When any JPA enabled object ( in this case a ProcessInstanceInfo ) is
persisted in JBPM, there are no transactions involved, and so the
EntityManager ( Hibernate ) decides to delay the insert ( queuing it as
there's no transaction in progress ). Then the processId never gets updated
and the NPE arises.
The problem here seems to be that both Drools and JBPM manage persistence
in different and incompatible ways. We've been able to modify
jbpm-persistence-jpa to open a JTA transaction before persisting
ProcessInstanceInfo, getting the EntityManager joining that transaction and
using the current Bitronix implementation already running in Drools ( to
assist persistence for their objects ) .. like so:
public void setKnowledgeRuntime(InternalKnowledgeRuntime kruntime) {
this.kruntime = kruntime;
Environment env = kruntime.getEnvironment();
Object tm = env.get( EnvironmentName.TRANSACTION_MANAGER );
if (!(tm instanceof javax.transaction.TransactionManager)) {
try {
// get Bitronix instance inside ...
java.lang.reflect.Field field =
tm.getClass().getDeclaredField("tm");
// who says private in Java is really private ... xD
field.setAccessible(true);
tm = field.get(tm);
} catch (Exception e){
e.printStackTrace();
}
}
this.txm = new JtaTransactionManager( env.get(
EnvironmentName.TRANSACTION ), env.get(
EnvironmentName.TRANSACTION_SYNCHRONIZATION_REGISTRY ), tm );
}
public void addProcessInstance(ProcessInstance processInstance) {
ProcessInstanceInfo processInstanceInfo = new ProcessInstanceInfo(
processInstance, this.kruntime.getEnvironment() );
ProcessPersistenceContext context =
((ProcessPersistenceContextManager) this.kruntime.getEnvironment().get(
EnvironmentName.PERSISTENCE_CONTEXT_MANAGER
)).getProcessPersistenceContext();
this.txm.begin();
context.persist( processInstanceInfo );
this.txm.commit();
I think we can agree that the previous lines of code are not the most
elegant solution ( at least not for me ).
So, Is there any timeline for merging DROOLS and JBPM 5 persistence
managers?
If someone gives me advice and architectural hints ( and if it is doable in
a reasonable ammount of time ) I would be eager to submit a patch for this
....
Alberto R. Galdo
argaldo(a)gmail.com
On Wed, Mar 14, 2012 at 13:56, Alberto R. Galdo <argaldo(a)gmail.com> wrote:
Great news!
We were in the process of debugging JBPM trying to find the source of the
bug ... and maybe days away from the solution ...
Is there any bug report in Jira and/or a patch we can apply without having
to wait for the next release so we can quick-patch our systems?
Alberto R. Galdo
argaldo(a)gmail.com
On Wed, Mar 14, 2012 at 13:09, Marco Rietveld <mrietvel(a)redhat.com> wrote:
>
> Hi Alberto,
>
> This is a bug that has been fixed in jBPM. It had to do with lazy
> initialization of a JPAProcessInstanceManager field.
>
> We'll be releasing a new jBPM version sometime soon (synchronous with
> Drools, I think). The bug is fixed in there.
>
> Regards,
> Marco
>
> 03/08/2012 11:32 AM, Alberto R. Galdo:
>
> Hi,
>
> We're running an application that uses Drools + JBPM 5 + Drools
> integration our set-up can be seen as:
>
> Some rule fires and creates a JBPM process ( a fact gets inserted
> into drools using
> "kcontext.getKnowledgeRuntime().startProcess("testProcess")" ).
We have a
> problem with the persistence of this processes. Persistence is implemented
> with JPA and JTA. Our application runs with fireUntilHalt() and when a
> process is launched from the consequence of any of the rules the
> persistence of the process fails. If the application runs with
> fireAllRules(), the persistence works like a charm.
>
> The error shown is as follow:
>
> Exception in thread "Thread-5" Exception executing consequence for rule
> "Run Process" in com.sample: java.lang.NullPointerException
> at
>
org.drools.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
> at
> org.drools.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1101)
> at org.drools.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1029)
> at
> org.drools.common.DefaultAgenda.fireUntilHalt(DefaultAgenda.java:1229)
> at
>
org.drools.common.AbstractWorkingMemory.fireUntilHalt(AbstractWorkingMemory.java:754)
> at
>
org.drools.common.AbstractWorkingMemory.fireUntilHalt(AbstractWorkingMemory.java:730)
> at
>
org.drools.command.runtime.rule.FireUntilHaltCommand$1.run(FireUntilHaltCommand.java:50)
> at java.lang.Thread.run(Thread.java:662)
> Caused by: java.lang.NullPointerException
> at
>
org.jbpm.persistence.processinstance.JPAProcessInstanceManager.addProcessInstance(JPAProcessInstanceManager.java:44)
> at
>
org.jbpm.process.instance.AbstractProcessInstanceFactory.createProcessInstance(AbstractProcessInstanceFactory.java:36)
> at
>
org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:182)
> at
>
org.jbpm.process.instance.ProcessRuntimeImpl.createProcessInstance(ProcessRuntimeImpl.java:154)
> at
>
org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:135)
> at
>
org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:130)
> at
>
org.drools.common.AbstractWorkingMemory.startProcess(AbstractWorkingMemory.java:1074)
> at
>
org.drools.impl.StatefulKnowledgeSessionImpl.startProcess(StatefulKnowledgeSessionImpl.java:301)
> at
> com.sample.Rule_Run_Process.defaultConsequence(Rule_Run_Process.java:9)
> at
> com.sample.Rule_Run_ProcessDefaultConsequenceInvoker.evaluate(Unknown
> Source)
> at
> org.drools.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1091)
> ... 6 more
> The problem is in this function:
> public void addProcessInstance(ProcessInstance processInstance) {
> ProcessInstanceInfo processInstanceInfo = new
> ProcessInstanceInfo( processInstance, this.kruntime.getEnvironment() );
> ProcessPersistenceContext context
> = ((ProcessPersistenceContextManager)
> this.kruntime.getEnvironment()
> .get( EnvironmentName.PERSISTENCE_CONTEXT_MANAGER ))
> .getProcessPersistenceContext();
> // @PrePersist added to ProcessInstanceInfo because of this
> context.persist( processInstanceInfo );
> ((org.jbpm.process.instance.ProcessInstance)
> processInstance).setId( processInstanceInfo.getId() );
> processInstanceInfo.updateLastReadDate();
> internalAddProcessInstance(processInstance);
> }
> We think after that persist sentence, the entity manager would have to
> run a flush sentence for the process instance is inserted into database and
> get the ID.
> Greets.
>
>
> _______________________________________________
> rules-users mailing
listrules-users@lists.jboss.orghttps://lists.jboss.org/mailman/listinfo/rules-users
>
>
>
> --
> jBPM/Drools developer
> Utrecht, the Netherlands
>
>