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> 允许指定 scriptLanguage和script
手工任务
一个由外部人员执行的任务,但是没有指定是 一个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