Camunda如何使用条件事件(条件coe)
Camunda条件事件(Conditional Events):定义了一个事件,该事件在给定条件被求值为true时被触发。它可以作为事件子流程的起始事件、中间事件和边界事件。开始和边界事件可以是中断的和不中断的。在Camunda中,条件事件是在流程变量的帮助下触发的。
Camunda条件事件包括:Conditional Start Event(启动条件事件)、Intermediate Conditional Catch Event(中间捕获条件事件)、Conditional Boundary Event(边界条件事件)、Conditional Start Event for Event Sub Process(子流程条件事件)。
本文重点介绍Conditional Start Event(启动条件事件)和T Conditional Boundary Event(边界条件事件),其它事件请参考camunda官方文档:https://docs.camunda.org/manual/7.15/reference/bpmn20/events/
一、设计流程图
测试场景:通过报销流程模拟条件事件流程自动发起,如果报销金额大于10000元,将自动发起报销审批子流程,在财务审批环节,如果报销金额金额发生变化,自动触发边界条件事件,退后给审批人。
报销主流程:
报销事件节点配置:
代理类代码如下:
package com.example.demo1;import org.camunda.bpm.engine.RuntimeService;import org.camunda.bpm.engine.delegate.DelegateExecution;import org.camunda.bpm.engine.delegate.javaDelegate;import org.camunda.bpm.engine.runtime.ProcessInstance;import java.util.List;/** * 触发条件事件启动子流程 */public class InstantiateProcessByConditionDelegate implements JavaDelegate { public void execute(DelegateExecution execution) { Integer money = (int)execution.getVariable("money"); RuntimeService runtimeService = execution.getProcessEngineServices().getRuntimeService(); List<ProcessInstance> instances = runtimeService .createConditionEvaluation() .setVariable("money", money) .evaluateStartConditions(); }}
BPMN流程模型文件:
<?xml version="1.0" encoding="UTF-8"?><bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1ktuxzn" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.15.0"> <bpmn:process id="Process_10z1wy2" name="报销主流程" isExecutable="true"> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>Flow_0f0u4dp</bpmn:outgoing> </bpmn:startEvent> <bpmn:sequenceFlow id="Flow_0f0u4dp" sourceRef="StartEvent_1" targetRef="Activity_02e4hhc" /> <bpmn:sequenceFlow id="Flow_0ckn1r7" sourceRef="Activity_02e4hhc" targetRef="Activity_1lkdefp" /> <bpmn:endEvent id="Event_1iic3x0"> <bpmn:incoming>Flow_04z0quc</bpmn:incoming> </bpmn:endEvent> <bpmn:sequenceFlow id="Flow_04z0quc" sourceRef="Activity_1lkdefp" targetRef="Event_1iic3x0" /> <bpmn:serviceTask id="Activity_02e4hhc" name="报销事件" camunda:class="com.example.demo1.InstantiateProcessByConditionDelegate"> <bpmn:incoming>Flow_0f0u4dp</bpmn:incoming> <bpmn:outgoing>Flow_0ckn1r7</bpmn:outgoing> </bpmn:serviceTask> <bpmn:userTask id="Activity_1lkdefp" name="通知报销人" camunda:assignee="demo"> <bpmn:incoming>Flow_0ckn1r7</bpmn:incoming> <bpmn:outgoing>Flow_04z0quc</bpmn:outgoing> </bpmn:userTask> </bpmn:process> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_10z1wy2"> <bpmndi:BPMNEdge id="Flow_0f0u4dp_di" bpmnElement="Flow_0f0u4dp"> <di:waypoint x="215" y="117" /> <di:waypoint x="270" y="117" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_0ckn1r7_di" bpmnElement="Flow_0ckn1r7"> <di:waypoint x="370" y="117" /> <di:waypoint x="430" y="117" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_04z0quc_di" bpmnElement="Flow_04z0quc"> <di:waypoint x="530" y="117" /> <di:waypoint x="592" y="117" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> <dc:Bounds x="179" y="99" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Event_1iic3x0_di" bpmnElement="Event_1iic3x0"> <dc:Bounds x="592" y="99" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Activity_09rzn3u_di" bpmnElement="Activity_02e4hhc"> <dc:Bounds x="270" y="77" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Activity_1khoz85_di" bpmnElement="Activity_1lkdefp"> <dc:Bounds x="430" y="77" width="100" height="80" /> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></bpmn:definitions>
报销审批子流程:
Conditional Start Event(启动条件事件)节点配置:
${money>=10000} 表示报销金额大于等于1万元,流程自动启动。
Conditional Boundary Event(边界条件事件)节点配置:
${money>=20000}表示报销金额大于等于2万元,自动触发边界条件事件。
BPMN流程模型文件:
<?xml version="1.0" encoding="UTF-8"?><bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1n4m8dk" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.15.0"> <bpmn:process id="Process_0uf5zc5" name="条件事件流程" isExecutable="true"> <bpmn:sequenceFlow id="Flow_1f7cdrv" sourceRef="StartEvent_1" targetRef="Activity_15fulz2" /> <bpmn:sequenceFlow id="Flow_0p7c5lt" sourceRef="Activity_15fulz2" targetRef="Activity_0xikne3" /> <bpmn:endEvent id="Event_152527w"> <bpmn:incoming>Flow_1l03vwj</bpmn:incoming> </bpmn:endEvent> <bpmn:sequenceFlow id="Flow_1l03vwj" sourceRef="Activity_0xikne3" targetRef="Event_152527w" /> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>Flow_1f7cdrv</bpmn:outgoing> <bpmn:conditionalEventDefinition id="ConditionalEventDefinition_0lzdf7y" camunda:variableName="money"> <bpmn:condition xsi:type="bpmn:tFormalExpression">${money>=10000}</bpmn:condition> </bpmn:conditionalEventDefinition> </bpmn:startEvent> <bpmn:userTask id="Activity_15fulz2" name="经理审批" camunda:assignee="demo"> <bpmn:incoming>Flow_1f7cdrv</bpmn:incoming> <bpmn:incoming>Flow_08he9tn</bpmn:incoming> <bpmn:outgoing>Flow_0p7c5lt</bpmn:outgoing> </bpmn:userTask> <bpmn:userTask id="Activity_0xikne3" name="财务审批" camunda:assignee="demo"> <bpmn:incoming>Flow_0p7c5lt</bpmn:incoming> <bpmn:outgoing>Flow_1l03vwj</bpmn:outgoing> </bpmn:userTask> <bpmn:boundaryEvent id="Event_0mnbhru" name="报销费修改事件" attachedToRef="Activity_0xikne3"> <bpmn:outgoing>Flow_08he9tn</bpmn:outgoing> <bpmn:conditionalEventDefinition id="ConditionalEventDefinition_19eu007" camunda:variableName="money"> <bpmn:condition xsi:type="bpmn:tFormalExpression">${money>=20000}</bpmn:condition> </bpmn:conditionalEventDefinition> </bpmn:boundaryEvent> <bpmn:sequenceFlow id="Flow_08he9tn" sourceRef="Event_0mnbhru" targetRef="Activity_15fulz2" /> </bpmn:process> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0uf5zc5"> <bpmndi:BPMNEdge id="Flow_1f7cdrv_di" bpmnElement="Flow_1f7cdrv"> <di:waypoint x="215" y="117" /> <di:waypoint x="270" y="117" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_0p7c5lt_di" bpmnElement="Flow_0p7c5lt"> <di:waypoint x="370" y="117" /> <di:waypoint x="500" y="117" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_1l03vwj_di" bpmnElement="Flow_1l03vwj"> <di:waypoint x="600" y="117" /> <di:waypoint x="662" y="117" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_08he9tn_di" bpmnElement="Flow_08he9tn"> <di:waypoint x="550" y="175" /> <di:waypoint x="550" y="195" /> <di:waypoint x="320" y="195" /> <di:waypoint x="320" y="157" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="Event_1d290h0_di" bpmnElement="StartEvent_1"> <dc:Bounds x="179" y="99" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Activity_1hwmimx_di" bpmnElement="Activity_15fulz2"> <dc:Bounds x="270" y="77" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Event_152527w_di" bpmnElement="Event_152527w"> <dc:Bounds x="662" y="99" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Activity_10pf0x5_di" bpmnElement="Activity_0xikne3"> <dc:Bounds x="500" y="77" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Event_0bjat0x_di" bpmnElement="Event_0mnbhru"> <dc:Bounds x="532" y="139" width="36" height="36" /> <bpmndi:BPMNLabel> <dc:Bounds x="451" y="166" width="77" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></bpmn:definitions>
二、部署流程并测试验证
流程部署后,查看数据库流程订阅事件表act_ru_event_subscr,发现Conditional Start Event(条件启动事件)已持久化到数据库中。
通过demo用户登录camunda平台http://localhost:8080/camunda/app/tasklist/default/#/login,启动主流程模拟测试。
由于报销金额满足条件,所以子流程被自动触发启动:
手动子流程提交到下一节点:
此时,流程流转到了Conditional Boundary Event(边界条件事件)节点上,查看数据库表记录:
为了模拟触发Conditional Boundary Event,在camunda后台修改money变量值:
由于流程变量money变成了20000,满足了Conditional Boundary Event触发条件,所以流程自动流程到对应节点。
三、条件事件使用说明
- Conditional Start Event(启动条件事件)
条件启动事件(Conditional Start Event)可以通过计算某些条件来启动流程。一个流程可以有一个或多个条件启动事件。
如果满足了多个条件,则会触发相应数量的进程。
部署带有条件启动事件的流程定义时,需要考虑以下事项:
在给定的流程定义中,条件启动事件的条件必须是唯一的,也就是说,流程定义不能有多个条件相同的条件启动事件。如果两个或多个条件启动事件包含相同的条件,则引擎会在部署流程定义时抛出异常。
流程版本控制:在部署流程定义的新版本时,将取消前一个版本的条件订阅。新版本中没有出现的条件事件也是如此。
当启动一个流程实例时,可以在RuntimeService上使用以下方法触发一个条件启动事件:
List<ProcessInstance> instances = runtimeService .createConditionEvaluation() .setVariable("temperature", 24) .evaluateStartConditions();// orList<ProcessInstance> instances = runtimeService .createConditionEvaluation() .setVariables(variableMap).evaluateStartConditions();
所提供的变量用于计算条件。它们还将作为变量传递给新创建的流程实例。条件启动事件的XML表示是带有conditionalEventDefinition子元素的普通启动事件声明。
可选:将variableName属性添加到conditionalEventDefinition允许指定一个变量名,在该变量名上,条件事件的条件应专门计算。
<startEvent id="conditionalStartEvent"> <conditionalEventDefinition camunda:variableName="temperature"> <condition type="tFormalExpression">${temperature > 20}</condition> </conditionalEventDefinition></startEvent>
2、Conditional Boundary Event(边界条件事件)
条件边界事件(Conditional Boundary Event)就像一个观察者,如果满足一个特定的条件,它就会被触发。中断条件事件和非中断条件事件是有区别的。缺省情况下为中断事件。非中断事件导致原始活动未被中断,实例仍处于活动状态。相反,创建了一个额外的执行路径,采用事件的传出转换。一个不中断的条件事件可以被触发多次,只要它所附加的活动是活动的。
在非中断条件事件的XML表示中,cancelActivity属性被设置为false:
<boundaryEvent id="conditionalEvent" attachedToRef="taskWithCondition" cancelActivity="false"> <conditionalEventDefinition> <condition type="tFormalExpression">${var1 == 1}</condition> </conditionalEventDefinition></boundaryEvent>
参考:
https://docs.camunda.org/manual/7.15/reference/bpmn20/events/conditional-events/