bpmn2.0流程定义xml 解析

 

<definitions id="myProcesses"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 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">

  <process id="My business processs" name="myBusinessProcess">

      ...

  </process>
<definitions>

如上代码是流程定义xml的基本代码 definitions是根节点process 是每个流程的起点 必须有一个id和name 如果为process元素定义了name,它会被用做流程的key 如果没有指定name,id会被用做key。 注意key的规则与jPDL一样: 空格和非字母数字的字符会被下划线代替。

 

事件

?事件:空启动事件

<startEvent id="start"  name="myStart" />

空结束事件

<endEvent id="end" name="myEnd" />


最简单的流程定义
 <process id="noneStartEndEvent" name="BPMN2 Example none start and end event">

    <startEvent id="start" />

    <sequenceFlow id="flow1" name="fromStartToEnd"
      sourceRef="start" targetRef="end" />

    <endEvent id="end" name="End" />

  </process>

终止结束事件

终止结束事件会结束整个流程实例,而空结束事件只会结束当前流程路径。

<endEvent id="terminateEnd" name="myTerminateEnd">
  <terminateEventDefinition/>
</endEvent>

顺序流

连接线

<sequenceFlow id="myFlow" name="My Flow"
        sourceRef="sourceId" targetRef="targetId" />

顺序流条件

<sequenceFlow id=....>

<conditionExpression xsi:type="tFormalExpression">${amount >= 500}</conditionExpression>

</sequenceFlow>

默认顺序流
 认顺序流只会在活动或网关的 所有其他外向顺序流的condition条件为false时才会使用
 默认顺序流通过指定活动或网关的 'default' 属性 来使用。

网关

网关是用来控制流程中的流向的

没有定义条件的顺序流会永远被选择

<parallelGateway id="myJoin" name="My synchronizing join" gatewayDirection="converging" />

gatewayDirection属性:
  • unspecificed (默认):网关可能拥有多个 进入和外出顺序流。
  • mixed:网关必须拥有多个 进入和外出顺序流。
  • converging:网关必须拥有多个进入顺序流, 但是只能有一个外出顺序流。
  • diverging:网关必须拥有一个进入顺序流, 和多个外出顺序流。

 

唯一网关(XOR 网关

 

一个流程中的唯一决策。 会有一个外向顺序流被使用?如果多个条件 执行为true,第一个遇到的就会被使用

 <process id="exclusiveGateway" name="BPMN2 Example exclusive gateway">

    <startEvent id="start" />

   <sequenceFlow id="flow1" name="fromStartToExclusiveGateway"
      sourceRef="start" targetRef="decideBasedOnAmountGateway" />

//定义网关
   <exclusiveGateway id="decideBasedOnAmountGateway" name="decideBasedOnAmount" />  
//第一个分支
   <sequenceFlow id="flow2" name="fromGatewayToEndNotEnough"
      sourceRef="decideBasedOnAmountGateway" targetRef="endNotEnough">
      <conditionExpression xsi:type="tFormalExpression">
        ${amount < 100}
      </conditionExpression>
   </sequenceFlow>
//第二个分支
   <sequenceFlow id="flow3" name="fromGatewayToEnEnough"
      sourceRef="decideBasedOnAmountGateway" targetRef="endEnough">
      <conditionExpression xsi:type="tFormalExpression">
        ${amount <= 500 && amount >= 100}
        </conditionExpression>
   </sequenceFlow>
//第三个分支
   <sequenceFlow id="flow4" name="fromGatewayToMoreThanEnough"
      sourceRef="decideBasedOnAmountGateway" targetRef="endMoreThanEnough">
      <conditionExpression xsi:type="tFormalExpression">
        ${amount > 500}
      </conditionExpression>
   </sequenceFlow>

   <endEvent id="endNotEnough" name="not enough" />

   <endEvent id="endEnough" name="enough" />

   <endEvent id="endMoreThanEnough" name="more than enough" />

  </process>

网关所需变量的提供
Map<String, Object> vars = new HashMap<String, Object>(); vars.put("amount", amount); ProcessInstance processInstance = executionService.startProcessInstanceByKey("exclusiveGateway", vars);

xor网关的默认走向 (如果所有条件都是false)

<exclusiveGateway id="decision" name="decideBasedOnAmountAndBankType" default="myFlow"/>

<sequenceFlow id="myFlow" name="fromGatewayToStandard"
    sourceRef="decision" targetRef="standard">
</sequenceFlow>

并行网关 (不带条件)

并行网关用来切分或同步相关的进入或外出 顺序流。

一进多出的流程设计:并行切分

多进一处的流程设计:并行归并

基本定义

  <process id="parallelGateway" name="BPMN2 example parallel gatewar">
 //空启动事件
    <startEvent id="Start" />
//连接空启动时间和并行网关
    <sequenceFlow id="flow1" name="fromStartToSplit"
      sourceRef="Start"
      targetRef="parallelGatewaySplit"  />
//并行网关1
    <parallelGateway id="parallelGatewaySplit" name="Split"
      gatewayDirection="diverging"/>
//并行网关1连接节点1
    <sequenceFlow id="flow2a" name="Leg 1"
      sourceRef="parallelGatewaySplit"
      targetRef="prepareShipment" />
//定义节点1
    <userTask id="prepareShipment" name="Prepare shipment"
      implementation="other" />
//节点1连接并行网关2
    <sequenceFlow id="flow2b" name="fromPrepareShipmentToJoin"
      sourceRef="prepareShipment"
      targetRef="parallelGatewayJoin"  />
//节点2连接并行网关1
    <sequenceFlow id="flow3a" name="Leg 2"
      sourceRef="parallelGatewaySplit"
      targetRef="billCustomer" />
//定义节点2
    <userTask id="billCustomer" name="Bill customer"
      implementation="other" />
//节点2连接并行网关2
    <sequenceFlow id="flow3b" name="fromLeg2ToJoin"
      sourceRef="billCustomer"
      targetRef="parallelGatewayJoin"  />
//定义并行网关2
    <parallelGateway id="parallelGatewayJoin" name="Join"
      gatewayDirection="converging"/>
//并行网关2连接空结束事件
    <sequenceFlow id="flow4"
      sourceRef="parallelGatewayJoin"
      targetRef="End">
    </sequenceFlow>

    <endEvent id="End" name="End" />

  </process>

包含网关?OR-gatewa (带条件)

进行“条件性”切分或汇聚顺序流。

 

<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>

?任务

 

人工任务(用户任务 user task

一个新人工任务就会被创建,交给用户的任务列表

<userTask id="myTask" name="My task" />
使用多种实现(WebService, WS-humantask,等等)

<userTask id="myTask" name="My task">
  <potentialOwner resourceRef="manager" jbpm:type="group">
    <resourceAssignmentExpression>
      <formalExpression>management</formalExpression>
    </resourceAssignmentExpression>
  </potentialOwner>
</userTask>


resourceAssignmentExpression 分配任务
potentialOwner 候选人
jbpm:type="group" 定义这是一个用户组的分配方式 如果删除了这个属性,就会默认使用用户组的语法


jbpm:type="user" 分配方式是候选用户
<userTask id="myTask" name="My User task">
  <potentialOwner resourceRef="employee" jbpm:type="user">
    <resourceAssignmentExpression>
      <formalExpression>peter</formalExpression>
    </resourceAssignmentExpression>
  </potentialOwner>
</userTask>
Peter将可以看到任务,因为他是这个任务的候选用户。
List<Task> tasks = taskService.createTaskQuery().candidate("peter").list();


用户组的定义
identityService.createGroup("management");

identityService.createUser("peter", "Peter", "Pan");
identityService.createMembership("peter", "management");

identityService.createUser("mary", "Mary", "Littlelamb");
identityService.createMembership("mary", "management");

所在用户组的人能看到这个任务
// Peter and Mary are both part of management, so they both should see the task
List<Task> tasks = taskService.findGroupTasks("peter");
assertEquals(1, tasks.size());
 tasks = taskService.findGroupTasks("mary");
assertEquals(1, tasks.size());

// Mary claims the task
Task task = tasks.get(0);
taskService.takeTask(task.getId(), "mary");
assertNull(taskService.createTaskQuery().candidate("peter").uniqueResult());

taskService.completeTask(task.getId());
assertProcessInstanceEnded(processInstance);
human performer 一个任务直接分配给一个人, 组,角色时
<userTask id="myTask" name="My User task">
  <humanPerformer resourceRef="employee">
    <resourceAssignmentExpression>
      <formalExpression>mary</formalExpression>
    </resourceAssignmentExpression>
  </humanPerformer>
</userTask>

任务列表中看到这个任务:

List<Task> tasks = taskService.findPersonalTasks("mary");
因为任务分配已经完成,通过使用 formalExpression,它也可以定义表达式 在运行期解析、
比如,如果流程变量'user'被定义了,然后,它可以用在表达式中。
<userTask id="myTask" name="My User task">
  <humanPerformer resourceRef="employee">
    <resourceAssignmentExpression>
      <formalExpression>${user}</formalExpression>
    </resourceAssignmentExpression>
  </humanPerformer>
</userTask>

Java服务任务

Service Task是一个自动活动,它会调用一些服务, 比如web service,java service等等。

<serviceTask id="MyServiceTask" name="My service task"
  implementation="Other" operationRef="myOperation" />
implementation 服务的类型 ->WebService, Other或者Unspecified
<interface id="myInterface"
    name="org.jbpm.MyJavaServicek">
    <operation id="myOperation2" name="myMethod">
      <inMessageRef>inputMessage</inMessageRef>
      <outMessageRef>outputMessage</outMessageRef>
    </bpmn:operation>
</interface>
备注:每个操作都至少有一个 输入信息,并且 最多有一个输出信息
<message id="inputMessage" name="input message" structureRef="myItemDefinition1" />

脚本任务

脚本任务时一个自动活动,当到达这个任务的时候 流程引擎会执行一个脚本。

<scriptTask id="scriptTask" name="Script Task" scriptLanguage="bsh">
  <script><![CDATA[
    for(int i=0; i < input.length; i++){
      System.out.println(input[i] + " x 2 = " + (input[i]*2));
    }]]>
  </script>
</scriptTask>
允许指定 scriptLanguagescript

手工任务

一个由外部人员执行的任务,但是没有指定是 一个BPM系统或是一个服务会被调用

<manualTask id="myManualTask" name="Call customer" />

java接收任务

receive task是一个任务会等到外部消息的到来。

<receiveTask id="receiveTask" name="wait" />


内嵌子流程

<process id="embeddedSubprocess">

    <startEvent id="theStart" />
    <sequenceFlow id="flow1" sourceRef="theStart" targetRef="receiveOrder" />
    <receiveTask name="Receive order" id="receiveOrder" />
    <sequenceFlow id="flow2" sourceRef="receiveOrder" targetRef="checkCreditSubProcess" />
    <subProcess id="checkCreditSubProcess" name="Credit check">

      ...

    </subProcess>

    <sequenceFlow id="flow9" sourceRef="checkCreditSubProcess" targetRef="theEnd" />
    <endEvent id="theEnd" />

</process>

定时启动事件

<startEvent name="Every Monday morning" id="myStart">
  <timerEventDefinition/>
</startEvent>

定义方法:
1.timeDate
<startEvent id="myStartEvent" >
  <timerEventDefinition>
    <timeDate>10/10/2099 00:00:00</timeDate>
  </timerEventDefinition>
</startEvent>

2.timeCycle (延迟)
<startEvent id="myStartEvent" >
  <timerEventDefinition>
    <timeCycle>5 hours</timeCycle>
  </timerEventDefinition>
</startEvent>
3.表达式 (每周五23点)
<startEvent id="myStartEvent" >
  <timerEventDefinition>
    <timeCycle>0 0 23 ? * FRI</timeCycle>
</timerEventDefinition>
</startEvent>

中间事件

间事件用来表示在流程执行过程中发生的事件(比如, 在流程启动之后,在它完成之前)。

定时器事件,触发事件,传播事件

?中间事件既可以抛出也可以捕获:
  • 抛出:当一个流程到达事件中, 它会立刻触发一个对应的触发器(一个激活,一个错误,等等)。
  • 捕获:当一个流程到达事件中, 它会等待一个对应的触发器发生(一个错误,一个定时器,等等)。

定时器

内部定时器事件用来表示一个流程的延迟。 直接的用例是收集数据, 只在没有人工作的晚上执行大量的逻辑,等等。

 

 

 

 

原文:http://www.mossle.com/docs/jbpm4devguide/html/bpmn2.html