[jbpm-commits] JBoss JBPM SVN: r6089 - in jbpm4/trunk/modules: devguide/src/main/docbook/en/images and 7 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Mon Jan 18 15:15:24 EST 2010
Author: jbarrez
Date: 2010-01-18 15:15:23 -0500 (Mon, 18 Jan 2010)
New Revision: 6089
Added:
jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.inclusive.gateway.merging.and.splitting.png
jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.inclusive.gateway.png
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/bpmn/gateway/inclusive/
jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/bpmn/gateway/inclusive/InclusiveGatewayTest.java
jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/bpmn/gateway/inclusive/
jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/bpmn/gateway/inclusive/inclusive_gateway.bpmn.xml
jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/bpmn/nested_inclusive_gateway_test.png
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/AbstractMergingGatewayActivity.java
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/InclusiveGatewayActivity.java
jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml
jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/gateway/InclusiveGatewayTest.java
Log:
JBPM-2738: added documentation for inclusive gateway. Worked on the nested inclusive gateway test case (not yet functioning - commented out)
Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/AbstractMergingGatewayActivity.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/AbstractMergingGatewayActivity.java 2010-01-18 15:01:34 UTC (rev 6088)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/AbstractMergingGatewayActivity.java 2010-01-18 20:15:23 UTC (rev 6089)
@@ -33,6 +33,7 @@
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.model.Activity;
import org.jbpm.pvm.internal.model.ExecutionImpl;
+import org.jbpm.pvm.internal.model.Transition;
/**
* Superclass for gateway activities that wait on multiple incoming executions before merging
@@ -105,13 +106,11 @@
session.lock(execution.getParent(), lockMode);
execution.setState(Execution.STATE_INACTIVE_JOIN);
- execution.waitForSignal();
-
- return isComplete(execution);
- } else {
- throw new JbpmException("invalid execution state: " + execution.getState());
}
+
+ execution.waitForSignal();
+ return isComplete(execution);
}
/**
@@ -123,8 +122,12 @@
protected ExecutionImpl join(ExecutionImpl execution) {
Activity activity = execution.getActivity();
ExecutionImpl concurrentRoot = execution.getParent();
+
+ if (concurrentRoot == null) {
+ return execution;
+ }
+
List<ExecutionImpl> joinedExecutions = getJoinedExecutions(concurrentRoot, activity);
-
endJoinedExecutions(joinedExecutions);
ExecutionImpl outgoingExecution = null;
Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/InclusiveGatewayActivity.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/InclusiveGatewayActivity.java 2010-01-18 15:01:34 UTC (rev 6088)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/InclusiveGatewayActivity.java 2010-01-18 20:15:23 UTC (rev 6089)
@@ -40,19 +40,19 @@
private static final Log LOG = Log.getLog(InclusiveGatewayActivity.class.getName());
public void fork(ExecutionImpl execution) {
- List<Transition> outgointSeqFlow = findOutgoingSequenceFlow(execution, CONDITIONS_CHECKED);
+ List<Transition> outgoingSeqFlow = findOutgoingSequenceFlow(execution, CONDITIONS_CHECKED);
- if (outgointSeqFlow.isEmpty()) {
+ if (outgoingSeqFlow.isEmpty()) {
Transition defaultSeqFlow = execution.getActivity().getDefaultOutgoingTransition();
if (defaultSeqFlow != null) {
- outgointSeqFlow.add(defaultSeqFlow);
+ outgoingSeqFlow.add(defaultSeqFlow);
} else {
throw new JbpmException("No sequenceFlow condition evaluated to true for " +
execution.getActivity() + " and no default sequenceFlow was speficied");
}
}
- proceed(execution, outgointSeqFlow);
+ proceed(execution, outgoingSeqFlow);
}
/**
Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.inclusive.gateway.merging.and.splitting.png
===================================================================
(Binary files differ)
Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.inclusive.gateway.merging.and.splitting.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.inclusive.gateway.png
===================================================================
(Binary files differ)
Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.inclusive.gateway.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml
===================================================================
--- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml 2010-01-18 15:01:34 UTC (rev 6088)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml 2010-01-18 20:15:23 UTC (rev 6089)
@@ -598,7 +598,7 @@
<section id="parallelGateway">
- <title>Gateway: parallel Gateway</title>
+ <title>Gateway: Parallel Gateway</title>
<para>
A parallel gateway is used to split or synchronize the respectively incoming or outgoing
@@ -688,6 +688,139 @@
</section>
+ <section id="inclusiveGateway">
+
+ <title>Gateway: Inclusive Gateway</title>
+
+ <para>
+ An inclusive gateway - also called an <emphasis role="bold">OR-gateway</emphasis> - is used
+ to 'conditionally' split or merge sequence flow. It basically behaves as a parallel
+ gateway, but it also takes in account conditions on the outgoing sequence flow (split behaviour)
+ and calculates if there are executions left that could reach the gateway (merge behaviour).
+ </para>
+
+ <para>
+ The inclusive gateway is depicted as a typical gateway shape with a circle inside (referring to 'OR' semantics).
+ Unlike the exclusive gateway, all condition expressions are evaluated (diverging or 'split' behaviour).
+ For every expression that evaluates to true, a new child execution is created.
+ Sequence flow without a condition will always be taken (ie. a child execution will always be
+ created in that case).
+ </para>
+
+ <para>
+ A converging inclusive gateway ('merge' behaviour) has a somewhat more difficult execution logic.
+ When an execution (Token in BPMN 2.0 terminology) arrives at the merging inclusive gateway,
+ the following is checked (quoting the specification literally):
+
+ <programlisting>
+For each empty incoming sequence flow, there is no
+Token in the graph anywhere upstream of this sequence flow, i.e., there is no directed path
+(formed by Sequence Flow) from a Token to this sequence flow unless
+a) the path visits the inclusive gateway or
+b) the path visits a node that has a directed path to a non-empty
+ incoming sequence flow of the inclusive gateway. "
+ </programlisting>
+
+ In more simple words: when an execution arrives at the gateway, all active execution are
+ checked if they can reach the inclusive gateway, by only taking in account the sequence flow
+ (note: conditions are not evaluated!). When the inclusive gateway is used, it is usally
+ used in a pair of splitting/merging inclusive gateways. In those cases, the execution
+ behaviour is easy enough to grasph by just looking at the model.
+
+ </para>
+
+ <para>
+ Of course, it is not hard to imagine situations where the executions are split and merged
+ in complex combinations using a variety of constructs including the inclusive gateway.
+ In those cases, it could very well be that the actual execution behaviour might not be what
+ the modelers' expects. So be careful when using the inclusive gateway and keep in mind
+ that it is often the best practice to use inclusive gateways just in pairs.
+ </para>
+
+ <para>
+ The following diagram shows how the inclusive gateway can be used.
+ (example taken from "BPMN method and style" by Bruce Silver)
+ <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.inclusive.gateway.png"/></imageobject></mediaobject>
+ We can distinguish following cases:
+ <itemizedlist>
+ <listitem>
+ <emphasis role="bold">Cash more than 10000 and not a foreign bank: </emphasis>Only the
+ "Large deposit" task will be active.
+ </listitem>
+ <listitem>
+ <emphasis role="bold">Cash more than 10000 and a foreign bank: </emphasis> Both the
+ "Large deposit" and "Foreign deposit" task will be active.
+ </listitem>
+ <listitem>
+ <emphasis role="bold">Cash lower than 10000 and a foreign bank: </emphasis> Only the
+ "Foreign deposit" task will be active.
+ </listitem>
+ <listitem>
+ <emphasis role="bold">Cash lower than 10000 and not a foreign bank: </emphasis> In this
+ case, both expressions evaluate to false. The default sequence flow will now be chosen.
+ In this example, this means that the "Standard deposit" task is active.
+ </listitem>
+ </itemizedlist>
+ No matter how many tasks are active after going through the inclusive gateway, the converging
+ inclusive gateway on the right will wait until all outgoing sequence flow of the inclusive
+ gateway on the left have reached the merging gateway (sometimes only one, sometimes two). Take a look at
+ <emphasis role="bold">org.jbpm.examples.bpmn.gateway.inclusive.InclusiveGatewayTest</emphasis>
+ to see how this example reflects in a unit test.
+ </para>
+
+ <para>
+ The XML version of the example above looks as follows:
+ <programlisting>
+<process id="inclusiveGateway" name="BPMN2 Example inclusive gateway">
+
+ <startEvent id="start" />
+
+ <sequenceFlow id="flow1" sourceRef="start" targetRef="inclusiveGatewaySplit" />
+
+ <emphasis role="bold"><inclusiveGateway id="inclusiveGatewaySplit" default="flow3"/></emphasis>
+
+ <sequenceFlow id="flow2" sourceRef=<emphasis role="bold">"inclusiveGatewaySplit"</emphasis> targetRef="largeDeposit">
+ <conditionExpression xsi:type="tFormalExpression">${cash > 10000}</conditionExpression>
+ </sequenceFlow>
+
+ <sequenceFlow id="flow3" sourceRef=<emphasis role="bold">"inclusiveGatewaySplit"</emphasis> targetRef="standardDeposit" />
+
+ <sequenceFlow id="flow4" sourceRef=<emphasis role="bold">"inclusiveGatewaySplit"</emphasis> targetRef="foreignDeposit">
+ <conditionExpression xsi:type="tFormalExpression">${bank == 'foreign'}</conditionExpression>
+ </sequenceFlow>
+
+ <userTask id="largeDeposit" name="Large deposit" />
+
+ <sequenceFlow id="flow5" sourceRef="largeDeposit" targetRef=<emphasis role="bold">"inclusiveGatewayMerge"</emphasis> />
+
+ <userTask id="standardDeposit" name="Standard deposit" />
+
+ <sequenceFlow id="flow6" sourceRef="standardDeposit" targetRef=<emphasis role="bold">"inclusiveGatewayMerge"</emphasis> />
+
+ <userTask id="foreignDeposit" name="Foreign deposit" />
+
+ <sequenceFlow id="flow7" sourceRef="foreignDeposit" targetRef=<emphasis role="bold">"inclusiveGatewayMerge"</emphasis> />
+
+ <emphasis role="bold"><inclusiveGateway id="inclusiveGatewayMerge" /></emphasis>
+
+ <sequenceFlow id="flow8" sourceRef="inclusiveGatewayMerge" targetRef="theEnd" />
+
+ <endEvent id="theEnd" />
+
+</process>
+ </programlisting>
+ </para>
+
+ <para>
+ As with any gateway type, the inclusive gateway type can have both merging and splitting
+ behaviour. In that case, the inclusive gateway will first wait until all executions
+ have arrived, before splitting again for every sequence flow that has a condition
+ that evauluates to true (or doesn't have a condition).
+ <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.inclusive.gateway.merging.and.splitting.png"/></imageobject></mediaobject>
+ </para>
+
+ </section>
+
<section id="task">
<title>Tasks</title>
Added: jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/bpmn/gateway/inclusive/InclusiveGatewayTest.java
===================================================================
--- jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/bpmn/gateway/inclusive/InclusiveGatewayTest.java (rev 0)
+++ jbpm4/trunk/modules/examples/src/test/java/org/jbpm/examples/bpmn/gateway/inclusive/InclusiveGatewayTest.java 2010-01-18 20:15:23 UTC (rev 6089)
@@ -0,0 +1,75 @@
+package org.jbpm.examples.bpmn.gateway.inclusive;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jbpm.api.NewDeployment;
+import org.jbpm.api.ProcessInstance;
+import org.jbpm.api.TaskQuery;
+import org.jbpm.api.task.Task;
+import org.jbpm.test.JbpmTestCase;
+
+
+public class InclusiveGatewayTest extends JbpmTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ NewDeployment deployment = repositoryService.createDeployment();
+ deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/gateway/inclusive/inclusive_gateway.bpmn.xml");
+ registerDeployment(deployment.deploy());
+ }
+
+ public void testLargeDeposit() {
+ Map<String, Object> vars = new HashMap<String, Object>();
+ vars.put("cash", 15000);
+ vars.put("bank", "local");
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("inclusiveGateway", vars);
+
+ TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstance.getId());
+ assertEquals(1, taskQuery.count());
+ Task largeDepositTask = taskQuery.uniqueResult();
+ assertEquals("Large deposit", largeDepositTask.getName());
+
+ taskService.completeTask(largeDepositTask.getId());
+ assertProcessInstanceEnded(processInstance);
+ }
+
+ public void testLargeForeignDeposit() {
+ Map<String, Object> vars = new HashMap<String, Object>();
+ vars.put("cash", 20000);
+ vars.put("bank", "foreign");
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("inclusiveGateway", vars);
+
+ TaskQuery taskQuery = taskService.createTaskQuery()
+ .processInstanceId(processInstance.getId()).orderAsc(TaskQuery.PROPERTY_NAME);
+ List<Task> tasks = taskQuery.list();
+ assertEquals(2, tasks.size());
+ assertEquals("Foreign deposit", tasks.get(0).getName());
+ assertEquals("Large deposit", tasks.get(1).getName());
+
+ for (Task task : tasks) {
+ taskService.completeTask(task.getId());
+ }
+
+ assertProcessInstanceEnded(processInstance);
+ }
+
+ public void testStandardDeposit() {
+ Map<String, Object> vars = new HashMap<String, Object>();
+ vars.put("cash", 7000);
+ vars.put("bank", "local");
+ ProcessInstance processInstance = executionService.startProcessInstanceByKey("inclusiveGateway", vars);
+
+ TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstance.getId());
+ assertEquals(1, taskQuery.count());
+ Task standardDeposit = taskQuery.uniqueResult();
+ assertEquals("Standard deposit", standardDeposit.getName());
+
+ taskService.completeTask(standardDeposit.getId());
+ assertProcessInstanceEnded(processInstance);
+ }
+
+
+}
Added: jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/bpmn/gateway/inclusive/inclusive_gateway.bpmn.xml
===================================================================
--- jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/bpmn/gateway/inclusive/inclusive_gateway.bpmn.xml (rev 0)
+++ jbpm4/trunk/modules/examples/src/test/resources/org/jbpm/examples/bpmn/gateway/inclusive/inclusive_gateway.bpmn.xml 2010-01-18 20:15:23 UTC (rev 6089)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 ../../../../../../../../../../bpmn/src/main/resources/BPMN20.xsd"
+ xmlns="http://schema.omg.org/spec/BPMN/2.0"
+ typeLanguage="http://www.w3.org/2001/XMLSchema"
+ expressionLanguage="http://www.w3.org/1999/XPath"
+ targetNamespace="http://jbpm.org/example/bpmn2/inclusive_gatewat"
+ xmlns:jbpm="http://jbpm.org/bpmn2">
+
+ <process id="inclusiveGateway" name="BPMN2 Example inclusive gateway">
+
+ <startEvent id="start" />
+
+ <sequenceFlow id="flow1" sourceRef="start" targetRef="inclusiveGatewaySplit" />
+
+ <inclusiveGateway id="inclusiveGatewaySplit" default="flow3"/>
+
+ <sequenceFlow id="flow2" sourceRef="inclusiveGatewaySplit" targetRef="largeDeposit">
+ <conditionExpression xsi:type="tFormalExpression">${cash > 10000}</conditionExpression>
+ </sequenceFlow>
+
+ <sequenceFlow id="flow3" sourceRef="inclusiveGatewaySplit" targetRef="standardDeposit" />
+
+ <sequenceFlow id="flow4" sourceRef="inclusiveGatewaySplit" targetRef="foreignDeposit">
+ <conditionExpression xsi:type="tFormalExpression">${bank == 'foreign'}</conditionExpression>
+ </sequenceFlow>
+
+ <userTask id="largeDeposit" name="Large deposit" />
+
+ <sequenceFlow id="flow5" sourceRef="largeDeposit" targetRef="inclusiveGatewayMerge" />
+
+ <userTask id="standardDeposit" name="Standard deposit" />
+
+ <sequenceFlow id="flow6" sourceRef="standardDeposit" targetRef="inclusiveGatewayMerge" />
+
+ <userTask id="foreignDeposit" name="Foreign deposit" />
+
+ <sequenceFlow id="flow7" sourceRef="foreignDeposit" targetRef="inclusiveGatewayMerge" />
+
+ <inclusiveGateway id="inclusiveGatewayMerge" />
+
+ <sequenceFlow id="flow8" sourceRef="inclusiveGatewayMerge" targetRef="theEnd" />
+
+ <endEvent id="theEnd" />
+
+ </process>
+
+</definitions>
Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/gateway/InclusiveGatewayTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/gateway/InclusiveGatewayTest.java 2010-01-18 15:01:34 UTC (rev 6088)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/gateway/InclusiveGatewayTest.java 2010-01-18 20:15:23 UTC (rev 6089)
@@ -120,6 +120,9 @@
" </process>" +
"</definitions>";
+ /*
+ * See test/resources/nested_inclusive_gateway_test.png
+ */
private static final String NESTED_INCLUSIVE_SPLIT =
"<definitions xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
" <process id='nestedInclusiveSplit' name='nestedInclusiveSplit' >" +
@@ -225,8 +228,8 @@
// If var == 9, the inclusive split will be reached and it will produce 2 outgoing sequence flow.
// The inclusive merge will have to merge three incoming sequence flow
- ProcessInstance pi = startAndVerifySimpleSplitProcess("nestedInclusiveSplit", 9, "wait1", "wait2");
- /*pi = executionService.signalExecutionById(pi.findActiveExecutionIn("wait1").getId());
+ /*ProcessInstance pi = startAndVerifySimpleSplitProcess("nestedInclusiveSplit", 9, "wait1", "wait2");
+ pi = executionService.signalExecutionById(pi.findActiveExecutionIn("wait1").getId());
assertActivitiesActive(pi.getId(), "wait2", "wait5", "wait6");
pi = executionService.signalExecutionById(pi.findActiveExecutionIn("wait5").getId());
pi = executionService.signalExecutionById(pi.findActiveExecutionIn("wait6").getId());
Added: jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/bpmn/nested_inclusive_gateway_test.png
===================================================================
(Binary files differ)
Property changes on: jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/bpmn/nested_inclusive_gateway_test.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
More information about the jbpm-commits
mailing list