If a join node is used with multiplicity="1" to join two possible outcome paths of a decision node, the join node sets the state of the branch executions to ended which is invalid if the execution path is a part of a concurrent execution: it prevents subsequent join nodes from destroying the incoming executions as they reach that node with "ended" state.
This behavior has been changed between JBPM 4.3 and 4.4: process definitions that utilize join nodes with multiplicity attributes to join conditional paths work correctly with JBPM 4.3 but fail with an exception in version 4.4.
For me, it seems that the implementation of the join node presumes that the state of branch executions have to be set to ended when a join node is reached, but there can be cases where this is not correct.
Let's see the following example: In this case join1 uses multiplicity="1" to wait only for one incoming execution. The execution is expected to pass through this node and reach join2 node where it will be ended:
<?xml version="1.0" encoding="UTF-8"?>
<process name="ForkJoinTest">
<start g="29,95,48,48" name="start1">
<transition g="-23,-25" name="to fork1" to="fork1"/>
</start>
<fork g="114,95,48,48" name="fork1">
<transition g="138,188:-50,-18" name="to script2" to="script2"/>
<transition g="139,72:-68,-18" name="to exclusive1" to="exclusive1"/>
</fork>
<script expr="Hello world!" g="230,162,92,52" name="script2" var="script2_msg">
<transition g="427,187:-29,4" name="to join2" to="join2"/>
</script>
<join g="347,51,48,48" multiplicity="1" name="join1">
<transition g="424,76:-7,-17" name="to join2" to="join2"/>
</join>
<join g="401,97,48,48" name="join2">
<transition g="-21,-21" name="to end1" to="end1"/>
</join>
<end g="490,97,48,48" name="end1"/>
<decision g="162,48,48,48" name="exclusive1">
<transition g="186,30:-12,-19" name="to script1" to="script1">
<condition expr="#
"/>
</transition>
<transition name="to join1" to="join1" g="-41,-18"/>
</decision>
<script expr="Hello world!" g="224,5,92,52" name="script1" var="script1_msg">
<transition g="371,31:-51,-15" name="to join1" to="join1"/>
</script>
</process>
This process definition works correctly with JBPM 4.3 but with JBPM 4.4 it fails with the following exception:
Exception in thread "main" org.jbpm.api.JbpmException: execution[ForkJoinTest.10001.to script2.10002] is not active: ended
at org.jbpm.pvm.internal.model.ExecutionImpl.checkActive(ExecutionImpl.java:1084)
at org.jbpm.pvm.internal.model.ExecutionImpl.take(ExecutionImpl.java:481)
at org.jbpm.jpdl.internal.activity.ForkActivity.execute(ForkActivity.java:95)
at org.jbpm.jpdl.internal.activity.ForkActivity.execute(ForkActivity.java:46)
at org.jbpm.pvm.internal.model.op.ExecuteActivity.perform(ExecuteActivity.java:60)
at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperationSync(ExecutionImpl.java:672)
at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperation(ExecutionImpl.java:632)
at org.jbpm.pvm.internal.model.ExecutionImpl.start(ExecutionImpl.java:217)
at org.jbpm.pvm.internal.cmd.StartProcessInstanceInLatestCmd.execute(StartProcessInstanceInLatestCmd.java:63)
at org.jbpm.pvm.internal.cmd.StartProcessInstanceInLatestCmd.execute(StartProcessInstanceInLatestCmd.java:36)
at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)
at org.jbpm.pvm.internal.tx.SpringCommandCallback.doInTransaction(SpringCommandCallback.java:45)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.jbpm.pvm.internal.tx.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:49)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)
at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:56)
at org.jbpm.pvm.internal.svc.ExecutionServiceImpl.startProcessInstanceByKey(ExecutionServiceImpl.java:67)