Red Hat Bugzilla – Bug 994475
NPE raises when trying to set process instance variable from DRL
Last modified: 2014-08-13 08:07:00 EDT
Created attachment 783811 [details]
NPE raises when trying to set process instance variable from DRL (activated in rule task):
Caused by: java.lang.NullPointerException
at org.jbpm.process.instance.impl.ProcessInstanceImpl.getProcess(ProcessInstanceImpl.java:89) [jbpm-flow-6.0.0.CR1.jar:6.0.0.CR1]
at org.jbpm.process.instance.impl.ProcessInstanceImpl.getContextInstance(ProcessInstanceImpl.java:158) [jbpm-flow-6.0.0.CR1.jar:6.0.0.CR1]
at org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl.setVariable(WorkflowProcessInstanceImpl.java:265) [jbpm-flow-6.0.0.CR1.jar:6.0.0.CR1]
at org.jboss.qa.bpms.clustering.Rule_initVariable1679671911DefaultConsequenceInvokerGenerated.evaluate(Unknown Source)
at org.jboss.qa.bpms.clustering.Rule_initVariable1679671911DefaultConsequenceInvoker.evaluate(Unknown Source)
at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1016) [drools-core-6.0.0.CR1.jar:6.0.0.CR1]
I will add the reproducer soon.
Here is the promised reproducer: https://github.com/droolsjbpm/jbpm/pull/175
It seems the exception raises only when persistence is configured.
I believe this is probably because process instances are serialized as part of the session state, but ProcessInstanceResolverStrategy should probably be used instead.
Could you verify, and would it be possible to register this strategy somehow as one of the defaults?
Kris, looks like it is caused by the disconnect on the transaction completion regardless if the marshaller strategy is default (serialized with all other facts) or we use process instance dedicated one. In both cases as soon as transaction ends given process instance is disconnected. Then the session is not loaded on every transaction which would make things work as then it would load the process instance with the dedicated strategy. So it must be done within the same transaction to have process instance entirely ready.
When using persistence, process instance is considered read only after transaction, that has done any modification to the process instance (like start process), is completed. So when process instance is inserted into ksession as a fact it shall only be used to read values from it. When attempting to modify its content (like setting variable) will fail unless it's reloaded. To secure proper access to "write" operations on process instance from within RHS following is recommended:
- load process instance once again from knowledge runtime before any "write" operations on process instance:
processInstance = (WorkflowProcessInstance)kcontext.getKnowledgeRuntime().getProcessInstance(processInstance.getId());
then use that processInstance to modify its state:
that way process instance will be reconnected with runtime engine and any changes to its state will be properly persisted.
Important to note is that process instance is not automatically updated within working memory when it changes outside - for example when process instance was inserted at the start of the process it will represent the state of the first wait state regardless if the process instance has already been moved further.
With that in mind it is recommended to insert process instance into working memory just before the actual rule evaluation rather than keeping it within working memory all the time. And retract it as soon as it's not needed any more.
Another important aspect when using rules that reason over process instances with persistence enabled is that before process completes the process instance MUST be retracted from working memory since on next ksession load it will fail to load process instance from db as it was already completed and removed from data base.
Code has been enhanced to use proper serialization mechanism for process instances (ProcessInstanceResolverStrategy) when using RuntimeManager. Committed to master and 6.0.x
Verified on ER4.