[jbpm-commits] JBoss JBPM SVN: r6157 - in jbpm4/trunk/modules: bpmn/src/main/java/org/jbpm/bpmn/parser and 3 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Wed Feb 3 08:19:58 EST 2010


Author: jbarrez
Date: 2010-02-03 08:19:58 -0500 (Wed, 03 Feb 2010)
New Revision: 6157

Added:
   jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.collapsed.subprocess.png
   jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.embedded.subprocess.png
   jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.nested.png
   jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.parallel.paths.png
   jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.two.endevents.png
Modified:
   jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessActivity.java
   jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessBinding.java
   jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.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/subprocess/SubProcessTest.java
Log:
JBPM-2740: added doc/example for embedded subprocess

Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessActivity.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessActivity.java	2010-02-02 17:32:58 UTC (rev 6156)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessActivity.java	2010-02-03 13:19:58 UTC (rev 6157)
@@ -29,7 +29,6 @@
 import org.jbpm.api.JbpmException;
 import org.jbpm.api.activity.ActivityExecution;
 import org.jbpm.api.model.Activity;
-import org.jbpm.api.model.OpenExecution;
 import org.jbpm.internal.log.Log;
 import org.jbpm.pvm.internal.model.ActivityImpl;
 import org.jbpm.pvm.internal.model.ExecutionImpl;

Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessBinding.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessBinding.java	2010-02-02 17:32:58 UTC (rev 6156)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/SubProcessBinding.java	2010-02-03 13:19:58 UTC (rev 6157)
@@ -69,7 +69,8 @@
         ActivityBehaviour activityBehaviour = ((ActivityImpl) childActivity).getActivityBehaviour();
         if ( (activityBehaviour instanceof BpmnEvent)
                 && !(activityBehaviour instanceof NoneStartEventActivity) ) {
-          parse.addProblem("Only none start events are allowed in an embedded sub process");
+          parse.addProblem("Only none start events are allowed in an embedded sub process. " +
+                  "Event " + childActivity.getName() + " has no incoming sequence flow.");
         } 
         
       }

Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java	2010-02-02 17:32:58 UTC (rev 6156)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.java	2010-02-03 13:19:58 UTC (rev 6157)
@@ -152,8 +152,6 @@
 
       // bind activities to their destinations
       parseSequenceFlow(processElement, parse, processDefinition);
-      
-      postParsingValidations(parse, processDefinition);
 
     } finally {
       parse.contextStackPop();
@@ -474,84 +472,4 @@
 
   }
   
-  /**
-   * Validations that are called at the end of the parsing: all activities,
-   * sequence flow, etc are fully available to allow detailed validations.
-   */
-  public void postParsingValidations(Parse parse, BpmnProcessDefinition processDefinition) {
-    validateSubProcessBoundaryNotCrossed(parse, processDefinition);
-  }
-  
-  /* ---------------------
-   * SUBPROCESS VALIDATION
-   * --------------------- */
-  
-  /**
-   * Validates that the boundary of a sub-process isn't crossed.
-   */
-  protected void validateSubProcessBoundaryNotCrossed(Parse parse, BpmnProcessDefinition processDefinition) {
-    for (Activity activity : processDefinition.getActivities()) {
-      ActivityImpl activityImpl = (ActivityImpl) activity;
-      if ( activityImpl.getActivityBehaviour() instanceof SubProcessActivity) {
-        validateSubProcessStartActivities(activityImpl, parse);
-        validateSubProcessAllSequenceFlow(activityImpl, parse);
-      }
-    }
-  }
-  
-  /**
-   * Only none start activities and activities without incoming sequence flow
-   * are allowed as start activities in a sub-process.
-   */
-  protected void validateSubProcessStartActivities(ActivityImpl subProcessActivity, Parse parse) {
-    for (Activity childActivity : subProcessActivity.getActivities()) {
-      if (childActivity.getIncomingTransitions().isEmpty()) {
-
-        ActivityBehaviour activityBehaviour = ((ActivityImpl) childActivity).getActivityBehaviour();
-        if ( (activityBehaviour instanceof BpmnEvent)
-                && !(activityBehaviour instanceof NoneStartEventActivity) ) {
-          parse.addProblem("Only none start events are allowed in an embedded sub process");
-        } 
-        
-      }
-    }
-  }
-  
-  /**
-   * Sequence flow are not allowed to cross the sub-process boundary.
-   * Exception to that rule is sequence flow which have as target a none start event (which actually
-   * could graphically be viewed as boundary events).
-   */
-  protected void validateSubProcessAllSequenceFlow(ActivityImpl subProcessActivity, Parse parse) {
-    
-    // collect all child activity ids
-    Set<String> childActivityIds = new HashSet<String>();
-    for (Activity childActivity : subProcessActivity.getActivities()) {
-      childActivityIds.add(childActivity.getName());
-    }
-    
-    // Verify source/target of all sequenceflow
-    for (Activity childActivity : subProcessActivity.getActivities()) {
-      for (Transition incomingTransition : childActivity.getIncomingTransitions()) {
-        validateSubProcessSequenceFlow(incomingTransition, childActivityIds, parse);          
-      }
-      for (Transition outgoingTransition : childActivity.getOutgoingTransitions()) {
-        validateSubProcessSequenceFlow(outgoingTransition, childActivityIds, parse);
-      }
-    }
-  }
-  
-  protected void validateSubProcessSequenceFlow(Transition transition, Set<String> subProcessActivityIds, Parse parse) {
-    if (!subProcessActivityIds.contains(transition.getSource().getName())) {
-      parse.addProblem("Invalid sequence flow " + transition.getName() 
-              + ": cannot cross sub-process boundaries from " + transition.getSource().getName()
-              + " into the sub process activity.");
-    }
-    if (!subProcessActivityIds.contains(transition.getDestination().getName())) {
-      parse.addProblem("Invalid sequence flow " + transition.getName() 
-              + ": cannot cross sub-process boundaries to " + transition.getSource().getName()
-              + " from within the sub process activity.");
-    }
-  }
-  
 }

Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.collapsed.subprocess.png
===================================================================
(Binary files differ)


Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.collapsed.subprocess.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.embedded.subprocess.png
===================================================================
(Binary files differ)


Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.embedded.subprocess.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.nested.png
===================================================================
(Binary files differ)


Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.nested.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.parallel.paths.png
===================================================================
(Binary files differ)


Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.parallel.paths.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.two.endevents.png
===================================================================
(Binary files differ)


Property changes on: jbpm4/trunk/modules/devguide/src/main/docbook/en/images/bpmn2.subprocess.two.endevents.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-02-02 17:32:58 UTC (rev 6156)
+++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml	2010-02-03 13:19:58 UTC (rev 6157)
@@ -1219,6 +1219,100 @@
   
     <title>Advanced constructs</title>
     
+    <section id="embeddedSubProcess">
+    
+      <title>Embedded sub-process</title>
+      
+      <para>
+        Subprocesses are in the first place a way of making a process "hierarchical", meaning that 
+        a modeller can create several 'levels' of detail. The top level view then explains the 
+        high-level way of doing things, while the lowest level focusses on the nitty gritty 
+        details.
+      </para>
+      
+      <para>
+        Take for example the following diagram. In this model, only the high level steps are shown.
+        The actual implementation of the &quot;Check credit&quot; step is hidden behind a
+        <emphasis role="bold">collapsed subprocess</emphasis>, which may be the perfect level
+        of detail to discuss business processes with end-users.
+        <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.collapsed.subprocess.png"/></imageobject></mediaobject>
+      </para>
+      
+      <para>
+        The second major use case for sub-processes is that the sub-process &quot;container&quot;
+        acts as a scope for events. When an event is fired from within the sub-process, the catch 
+        events on the boundary of the sub-process will be the first to receive this event.
+      </para>
+      
+      <para>
+        A sub-process that is defined within a top-level process is called an <emphasis role="bold">
+        embeddable sub-process</emphasis>. All process data that is available in the parent
+        process is also available in the sub-process. The following diagram shows the expanded
+        version of the model above.
+         <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.embedded.subprocess.png"/></imageobject></mediaobject>
+         The XML counterpart of this model looks as follows:$
+         <programlisting>
+&lt;process id=&quot;embeddedSubprocess&quot;&gt;
+
+    &lt;startEvent id=&quot;theStart&quot; /&gt;
+    &lt;sequenceFlow id=&quot;flow1&quot; sourceRef=&quot;theStart&quot; targetRef=&quot;receiveOrder&quot; /&gt;
+    &lt;receiveTask name=&quot;Receive order&quot; id=&quot;receiveOrder&quot; /&gt;
+    &lt;sequenceFlow id=&quot;flow2&quot; sourceRef=&quot;receiveOrder&quot; targetRef=&quot;checkCreditSubProcess&quot; /&gt;
+    <emphasis role="bold">&lt;subProcess id=&quot;checkCreditSubProcess&quot; name=&quot;Credit check&quot;&gt;</emphasis>
+    
+      ...
+
+    <emphasis role="bold">&lt;/subProcess&gt;</emphasis>
+    
+    &lt;sequenceFlow id=&quot;flow9&quot; sourceRef=&quot;checkCreditSubProcess&quot; targetRef=&quot;theEnd&quot; /&gt;
+    &lt;endEvent id=&quot;theEnd&quot; /&gt;
+
+&lt;/process&gt;
+         </programlisting>
+         Note that inside the sub-process, events, activities, tasks are defined as if it were
+         a top-level process (hence the three &quot;...&quot; within the XML example above. Sub-processes
+         are <emphasis role="bold">only allowed to have a none start event</emphasis>.
+      </para>
+      
+      <para>
+        Conceptually an embedded sub-process works as follows: when an execution arrives
+        at the subprocess, a child execution is created. The child execution can then later create
+        other (sub-)child executions, for example when a parallel gateway is used whithin the
+        sub-process. The sub-process however, is only completed when no executions are active anymore
+        within the subprocess. In that case, the parent execution is taken for further continuation
+        of the process.
+      </para>
+      <para>   
+        For example, in the following diagram, the &quot;Third task&quot;
+        will only be reached after both the &quot;First task&quot; and the &quot;Second task&quot;
+        are completed. Completing one of the tasks in the sub-process, will not trigger the
+        continuation of the sub-process, since one execution is still active within the sub-process.
+        <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.subprocess.two.endevents.png"/></imageobject></mediaobject>
+      </para>
+      
+      <para>
+        Sub-processes can have multiple start events. In that case, multiple parallel paths
+        will exist within the sub-process. The rules for sub-process completion are unchanged:
+        the sub-process will only be left when all the executions of the parallel paths are
+        ended.
+        <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.subprocess.parallel.paths.png"/></imageobject></mediaobject>
+      </para>
+      
+      <para>
+        Nested sub-processes are also possible. This way, the process can be divided into several
+        levels of detail. There is no limitation on the levels of nesting.
+        <mediaobject><imageobject><imagedata align="center" fileref="images/bpmn2.subprocess.nested.png"/></imageobject></mediaobject>
+      </para>
+      
+      <para>
+        Implementation note: According to the BPMN 2 specification, an activity without ougoing sequence
+        flow implicitly ends the current execution. However currently, it is necessary for a correct functioning to  
+        specifically use an end event within the sub-process to end a certain path. This will
+        be enhanced in the future to be specification-compliant.
+      </para>
+    
+    </section> <!-- End of embedded subprocess -->
+    
     <section id="Timer start event">
     
       <title>Timer start event</title>

Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/subprocess/SubProcessTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/subprocess/SubProcessTest.java	2010-02-02 17:32:58 UTC (rev 6156)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/subprocess/SubProcessTest.java	2010-02-03 13:19:58 UTC (rev 6157)
@@ -138,6 +138,33 @@
     "  </process>" +
     "</definitions>";
   
+  private static final String SUBPROCESS_WITH_UNJOINED_PATHS = 
+    "<definitions>" +
+    "  <process id='unjoinedPaths'>" +
+    "    <startEvent id='theStart' />" +
+    "    <sequenceFlow id='flow1' sourceRef='theStart' targetRef='mySubProcess' />" +
+    "    <subProcess id='mySubProcess'>" +
+    "      <startEvent id='subProcessStart' />" +
+    "      <sequenceFlow id='subFlow1' sourceRef='subProcessStart' targetRef='splitInSubProcess' />" +
+    "      <parallelGateway id='splitInSubProcess' />" +
+    "      <sequenceFlow id='subFlow2' sourceRef='splitInSubProcess' targetRef='subTask1' />" +
+    "      <sequenceFlow id='subFlow3' sourceRef='splitInSubProcess' targetRef='subTask2' />" +
+    "      <sequenceFlow id='subFlow4' sourceRef='splitInSubProcess' targetRef='subTask3' />" +
+    "      <userTask id='subTask1' name='firstTask' />" +
+    "      <userTask id='subTask2' name='secondTask' />" +
+    "      <userTask id='subTask3' name='thirdTask' />" +
+    "      <sequenceFlow id='subFlow4' sourceRef='subTask1' targetRef='subEnd1' />" +
+    "      <endEvent id='subEnd1' />" +
+    "      <sequenceFlow id='subFlow5' sourceRef='subTask2' targetRef='subEnd2' />" +
+    "      <endEvent id='subEnd2' />" +
+    "      <sequenceFlow id='subFlow6' sourceRef='subTask3' targetRef='subEnd3' />" +
+    "      <endEvent id='subEnd3' />" +
+    "    </subProcess>" +
+    "    <sequenceFlow id='flow2' sourceRef='mySubProcess' targetRef='theEnd' />" +
+    "    <endEvent id='theEnd' />" +
+    "  </process>" +
+    "</definitions>";
+  
   /**
    * Tests a simple sub process with sequentially one start, a user task and an end.
    */
@@ -241,5 +268,26 @@
     taskService.completeTask(tasks.get(0).getId());
     assertProcessInstanceEnded(pi);
   }
+  
+  /**
+   * Tests a process that has a sub-process which has a splitting parallelgatway without 
+   * a merging parallel gateway later on. This way, execution state juggling gets a bit trickier.
+   */
+  public void testSubProcessWithUnjoinedPaths() {
+    deployBpmn2XmlString(SUBPROCESS_WITH_UNJOINED_PATHS);
+    ProcessInstance pi = executionService.startProcessInstanceByKey("unjoinedPaths");
+    
+    TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderAsc(TaskQuery.PROPERTY_NAME);
+    List<Task> tasks = query.list();
+    assertEquals(3, tasks.size());
+    assertEquals("firstTask", tasks.get(0).getName());
+    assertEquals("secondTask", tasks.get(1).getName());
+    assertEquals("thirdTask", tasks.get(2).getName());
+    
+    taskService.completeTask(tasks.get(0).getId());
+    taskService.completeTask(tasks.get(1).getId());
+    taskService.completeTask(tasks.get(2).getId());
+    assertProcessInstanceEnded(pi);
+  }
 
 }



More information about the jbpm-commits mailing list