-
Bug
-
Resolution: Done
-
Major
-
jBPM 3.2.13
-
None
If you have any node before the fork that is asynchonous, the fork will not work as expected. It will create child tokens but they will not be "saved" into the "children" map of the parent (root) token. You can do the following test process:
1) Create a Start State going to 2)
2) Create a node flagged ASYNCHRONOUS with a "PrintTokens" action doing the following:
package test.actions; import org.jbpm.graph.def.ActionHandler; import org.jbpm.graph.exe.ExecutionContext; public class PrintTokens extends AbstractBpmHandler implements ActionHandler { @Override public void execute(ExecutionContext executionContext) throws Exception { System.out.println("PRINT TOKENS START"); System.out.println("TOKEN: " + executionContext.getToken().getId()); System.out.println("PARENT: " + (executionContext.getToken().getParent() != null ? executionContext.getToken().getParent().getId() : "null") ); System.out.println("PARENT CHILDREN: " + (executionContext.getToken().getParent() != null ? executionContext.getToken().getParent().getChildren() : "null")); System.out.println("PRINT TOKENS END"); executionContext.leaveNode(); } }
This node will go to 3)
3) Create a fork
4) create two SYNCHRONOUS nodes (node1 and node2) associated to the same action "PrintTokens" as 2) and create a transition from the fork to node1 and another from the fork to node 2
5) create a join and create a transition from node1 to the join and another transition from node2 to the join.
6) Create an END state and the transition from the join to the End state.
You will then see the following:
17:57:50,219 INFO [STDOUT] PRINT TOKENS START 17:57:50,220 INFO [STDOUT] TOKEN: 10931 17:57:50,221 INFO [STDOUT] PARENT: null 17:57:50,225 INFO [STDOUT] PARENT CHILDREN: null 17:57:50,228 INFO [STDOUT] PRINT TOKENS END 17:57:50,251 INFO [STDOUT] PRINT TOKENS START 17:57:50,251 INFO [STDOUT] TOKEN: 10941 17:57:50,252 INFO [STDOUT] PARENT: 10931 17:57:50,255 INFO [STDOUT] PARENT CHILDREN: {} 17:57:50,259 INFO [STDOUT] PRINT TOKENS END 17:57:50,273 INFO [STDOUT] PRINT TOKENS START 17:57:50,274 INFO [STDOUT] TOKEN: 10942 17:57:50,275 INFO [STDOUT] PARENT: 10931 17:57:50,278 INFO [STDOUT] PARENT CHILDREN: {} 17:57:50,279 INFO [STDOUT] PRINT TOKENS END 17:57:50,279 WARN [Token] Token(10931) was already unlocked
The children sets are EMPTY even if they should contain the two children of the fork !!!!
This means that when arriving to the join it will arrives into that part of the code:
... // if no configuration is specified else { // check all child tokens and reactivate the parent // when the last token arrives in the join Collection tokenNames = parentToken.getChildren().keySet(); reactivateParent = !parentToken.hasActiveChildren() && mustParentBeReactivated(parentToken, tokenNames); } ...
which will execute the getChildren method and so will return an empty set. This will allow the first token arrived into the join to reactivate the parent to continue the process. Then when the second child token arrives, it will do the same and then the nightmare begins. IN the test case I provide, there is just a warning saying that the token was already unlocked, but if you add another node after the join and, worse, if this node is asynchronous, you will get a bunch of exceptions.... meaning that in this test case, the join is not waiting on all the token before reactivating the root token !
By the way, you can do the same test case with setting the first not not asynchronous and you will get a working situation:
18:02:54,307 INFO [STDOUT] PRINT TOKENS START 18:02:54,307 INFO [STDOUT] TOKEN: 11041 18:02:54,308 INFO [STDOUT] PARENT: null 18:02:54,311 INFO [STDOUT] PARENT CHILDREN: null 18:02:54,316 INFO [STDOUT] PRINT TOKENS END 18:02:54,329 INFO [STDOUT] PRINT TOKENS START 18:02:54,330 INFO [STDOUT] TOKEN: 11052 18:02:54,332 INFO [STDOUT] PARENT: 11041 18:02:54,335 INFO [STDOUT] PARENT CHILDREN: {to Branch 1=Token(11052), to Branch 2=Token(11053)} 18:02:54,339 INFO [STDOUT] PRINT TOKENS END 18:02:54,351 INFO [STDOUT] PRINT TOKENS START 18:02:54,351 INFO [STDOUT] TOKEN: 11053 18:02:54,352 INFO [STDOUT] PARENT: 11041 18:02:54,356 INFO [STDOUT] PARENT CHILDREN: {to Branch 1=Token(11052), to Branch 2=Token(11053)} 18:02:54,359 INFO [STDOUT] PRINT TOKENS END
Just in case here is the content of the processdefinition.xml:
<?xml version="1.0" encoding="UTF-8"?> <process-definition xmlns="" name="ForkTest"> <start-state name="Start"> <transition to="Print Tokens"></transition> </start-state> <fork name="fork1"> <transition to="Print Token (1)" name="to Branch 1"></transition> <transition to="Print Token (2)" name="to Branch 2"></transition> </fork> <join name="join1"> <transition to="End"></transition> </join> <node name="Print Token (1)"> <action class="test.actions.PrintTokens"></action> <transition to="join1"></transition> </node> <node name="Print Token (2)"> <action class="test.actions.PrintTokens"></action> <transition to="join1"></transition> </node> <node name="Print Tokens" async="true"> <action class="test.actions.PrintTokens"></action> <transition to="fork1"></transition> </node> <end-state name="End"></end-state> </process-definition>