-
1. Re: concurrent execution
csouillard Feb 1, 2007 11:15 AM (in response to csouillard)I just see that my process is not visible... I will try again :
<flow> <links> <link name="four_to_one"/> <link name="one_to_two"/> </links> <sequence name="seq1"> <target linkName="four_to_one"/> <source linkName="one_to_two"/> </sequence> <sequence name="seq2"> <target linkName="one_to_two"/> </sequence> <sequence name="seq4"> <source linkName="four_to_one"/> </sequence> </flow>
-
2. Re: concurrent execution
tom.baeyens Feb 5, 2007 11:24 AM (in response to csouillard)each activity in a flow corresponds to a concurrent path of execution (=org.jbpm.pvm.Execution)
there are basically 2 ways on how to parse bpel flow xml into a pvm object model:
1) generate a set of nodes that are connected with transitions.
2) use a flow node with the concurrent activities as composite nodes inside the bpel flow node.
in both cases, the implementation of the flow should look like this:
for each concurrent activity, create a new org.jbpm.pvm.Execution make it point to the flow node and and launch it. launching is different in the 2 approaches.
in the transitions approach, launching is calling execution.takeTransition
in the composite nodes approach... hmmm need to think on that. -
3. Re: concurrent execution
aguizar Feb 8, 2007 11:16 PM (in response to csouillard)In the current implementation, concurrent activities appear as children of the Flow node. For each such activity, Flow creates an Execution, points it to the child activity and launches it. When the child activity completes, it notifies the Flow node. In turn, Flow examines the remaining Executions to determine if any is still active.
Links are not implemented as transitions. This is because control does not flow through links as it does through transitions. Links are just synchronization points.
The current implementation regards links as boolean variables. An activity that is the target of one or more links cannot execute until the link is resolved, i.e. the link variable is assigned a value.
In the absence of links, Charles' example launches three Executions, which proceed separately without synchronization.
Adding links does not cause an Execution to leave the source and enter the target.
Links just cause the Execution at the target to wait for another Execution to complete the source.
When launched, seq1 reads the value of link four_to_one. Because the link is unresolved (i.e. four_to_one is null), seq1 performs no action and returns. In turn, seq2 reads the value of link one_to_two. Again, the link is unresolved, hence seq2 simply returns. Finally seq4 executes (no link is targeted at it), completes and sets the value of four_to_one to true.
The Execution parked in the target activity, seq1, is notified that link four_to_one has been resolved. Since seq1 has no other links, the Execution performs the behavior of seq1.
In code, this means something likeclass Flow { List<Link> links; List<Activity> activities; void execute(Execution execution) { for (Link link : links) { LinkValue linkValue = new LinkValue(link); execution.setVariable(link.getName(), linkValue); } for (Activity activity : actitivites) { Execution childExecution = new Execution(execution); childExecution.setNode(activity); activity.enter(childExecution); } } } class Activity { List<Link> sourceLinks; List<Link> targetLinks; Expression joinCondition; void enter(Execution execution) { if (!areTargetLinksResolved(execution)) return; if (joinCondition.evaluate(execution)) execute(execution); else { resolveSourceLinks(execution, false); leave(execution); } } boolean areLinksResolved(Execution execution) { boolean resolved = true; for (Link link: targetLinks) { LinkValue linkValue = execution.getVariable(link.getName()); linkValue.setTargetExecution(execution); if (linkValue.getStatus() == null) resolved = false; } return resolved; } void resolveSourceLinks(Execution execution, boolean status) { for (Link link: targetLinks) { LinkValue linkValue = execution.getVariable(link.getName()); linkValue.setStatus(status); } } void linkResolved(Execution execution) { enter(execution); } abstract void execute(Execution execution); /* for a non-blocking activity looks like { doSpecificStuff(); resolveSourceLinks(execution, true); leave(execution); } */ } class LinkValue { Execution targetExecution; Boolean status; void setStatus(boolean status) { this.status = Boolean.valueOf(status); if (targetExecution != null) targetExecution.getNode().linkResolved(targetExecution); } }
Charles, does this resemble what you had in mind?