本人个人博客网站,欢迎访问:学教府
一、概述
边界事件:边界事件属于一种特殊的中间事件。区别是: 中间事件 可以单独作为流程元素存在于流程中,而 边界事件 必须附属于某个流程元素(如任务、子流程等)。边界事件是Catching事件。
注意:补偿事件的连接线需要用association,association必须放在所有标签最后。
二、定时器边界事件
- 说明:定时器边界事件会在定时器时间到了之后进行触发,需要开启异步执行器(在activiti.cfg.xml中)。此处模拟一个损坏的物品首先交给初级工程师修理,定时1分钟后没有修好就给中级工程师修理
- 流程图
- 流程的xml
<process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"> <startEvent id="startEvent1" name="StartEvent"/> <userTask activiti:exclusive="true" id="userTask1" name="初级工程师维修"/> <!--cancelActivity属性是触发边界事件后,原流程是否取消,为true是取消,取消是在数据库中删除对应的数据--> <boundaryEvent attachedToRef="userTask1" cancelActivity="true" id="boundaryEvent1"> <timerEventDefinition id="boundaryEvent1_ED_1"> <!--定时一分钟--> <timeDuration>PT1M</timeDuration> </timerEventDefinition> </boundaryEvent> <endEvent id="endEvent1" name="EndEvent"/> <userTask activiti:exclusive="true" id="userTask2" name="中级工程师维修"/> <sequenceFlow id="_7" sourceRef="startEvent1" targetRef="userTask1"/> <sequenceFlow id="_8" sourceRef="userTask1" targetRef="endEvent1"/> <sequenceFlow id="_9" sourceRef="boundaryEvent1" targetRef="userTask2"/> <sequenceFlow id="_10" sourceRef="userTask2" targetRef="endEvent1"/> </process>
- 编码发布
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); RuntimeService runtimeService = processEngine.getRuntimeService(); TaskService taskService = processEngine.getTaskService(); Deployment deployment = repositoryService.createDeployment().addClasspathResource("timer-boundary-event.bpmn").deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult(); ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId()); //首先由初级工程师维修 Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); System.out.println("当前任务:" + task.getName()); //等定时器1分钟过完,需要比一分钟时间长,防止步骤没执行完 Thread.sleep(100 * 1000); //定时器时间到了后会触发定时器边界事件,任务转到中级工程师 task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); System.out.println("当前任务:" + task.getName()); processEngine.close(); System.exit(0);
- 查看结果
三、错误边界事件
-
说明:当子流程中的ServiceTask抛出错误abc时,子流程的错误边界事件(定义错误引用为“abc”,没有具体的错误实现,则默认errorCode为引用的字符串“abc")会捕获该错误。 因此最终查询任务时是在ErrorTask
-
bpmn图
-
流程xml
<process id="process1" name="process"> <startEvent id="startEvent1" name="startEvent"></startEvent> <subProcess id="subProcess1" name="subProcess"> <startEvent id="startEvent2" name="startEvent"></startEvent> <serviceTask id="serviceTask1" name="Throw Error Task" activiti:class="com.xjf.test.delegate.ThrowErrorDelegate"></serviceTask> <endEvent id="endEvent1" name="endEvent"></endEvent> <sequenceFlow id="_1" sourceRef="startEvent2" targetRef="serviceTask1"></sequenceFlow> <sequenceFlow id="_2" sourceRef="serviceTask1" targetRef="endEvent1"></sequenceFlow> </subProcess> <boundaryEvent id="boundaryEvent1" attachedToRef="subProcess1" cancelActivity="false"> <!--引入的错误引用没有定义时,则errorCode就是引用的字符串,此处为“abc”--> <errorEventDefinition errorRef="abc"></errorEventDefinition> </boundaryEvent> <userTask id="ErrorTask" name="ErrorTask"></userTask> <userTask id="EndTask" name="EndTask"></userTask> <endEvent id="endEvent2" name="endEvent"></endEvent> <sequenceFlow id="_3" sourceRef="startEvent1" targetRef="subProcess1"></sequenceFlow> <sequenceFlow id="_4" sourceRef="boundaryEvent1" targetRef="ErrorTask"></sequenceFlow> <sequenceFlow id="_5" sourceRef="subProcess1" targetRef="EndTask"></sequenceFlow> <sequenceFlow id="_6" sourceRef="EndTask" targetRef="endEvent2"></sequenceFlow> </process>
委托类ThrowErrorDelegate:
String errorCode = "abc"; System.out.println("抛出错误:errorCode=" + errorCode); throw new BpmnError(errorCode);
-
编码发布
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); RuntimeService runtimeService = processEngine.getRuntimeService(); TaskService taskService = processEngine.getTaskService(); Deployment deployment = repositoryService.createDeployment().addClasspathResource("error-boundary-event.bpmn").deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult(); ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId()); Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); System.out.println("当前任务:" + task.getName()); processEngine.close(); System.exit(0);
-
查看结果
四、信号边界事件
- 说明:该事件接收到指定的信号后触发,不同的是信号事件是全局的,即信号不是只在一个流程实例中传递,而是所有流程实例都是一样的(一处发信号,所有信号的边界事件都能接收)。此处测试的就是两个流程实例接收同一个信号。
- bpmn图
- 流程xml
<process id="process" isClosed="false" name="process" processType="None"> <startEvent id="startEvent" name="startEvent"/> <userTask activiti:exclusive="true" id="checkContact" name="查看合同"/> <userTask activiti:exclusive="true" id="confirmContact" name="确认合同"/> <boundaryEvent attachedToRef="confirmContact" cancelActivity="true" id="boundaryEvent"> <signalEventDefinition id="boundaryEvent_ED_1" signalRef="contactChangeSignal"/> </boundaryEvent> <userTask activiti:exclusive="true" id="contactChange" name="合同变更"/> <userTask activiti:exclusive="true" id="signContact" name="签订合同"/> <endEvent id="endEvent" name="endEvent"/> <sequenceFlow id="_2" sourceRef="startEvent" targetRef="checkContact"/> <sequenceFlow id="_3" sourceRef="checkContact" targetRef="confirmContact"/> <sequenceFlow id="_4" sourceRef="boundaryEvent" targetRef="contactChange"/> <sequenceFlow id="_5" sourceRef="contactChange" targetRef="checkContact"/> <sequenceFlow id="_6" sourceRef="confirmContact" targetRef="signContact"/> <sequenceFlow id="_7" sourceRef="signContact" targetRef="endEvent"/> </process>
- 编码发布
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); RuntimeService runtimeService = processEngine.getRuntimeService(); TaskService taskService = processEngine.getTaskService(); Deployment deployment = repositoryService.createDeployment().addClasspathResource("signal-boundary-event.bpmn").deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult(); //启动两个流程实例 ProcessInstance pInstance1 = runtimeService.startProcessInstanceById(processDefinition.getId()); ProcessInstance pInstance2 = runtimeService.startProcessInstanceById(processDefinition.getId()); //将实例一进行到确认合同 Task pInstance1Task = taskService.createTaskQuery().processInstanceId(pInstance1.getId()).singleResult(); taskService.complete(pInstance1Task.getId()); pInstance1Task = taskService.createTaskQuery().processInstanceId(pInstance1.getId()).singleResult(); System.out.println("实例一当前任务:" + pInstance1Task.getName()); //将实例二进行到确认合同 Task pInstance2Task = taskService.createTaskQuery().processInstanceId(pInstance2.getId()).singleResult(); taskService.complete(pInstance2Task.getId()); pInstance2Task = taskService.createTaskQuery().processInstanceId(pInstance2.getId()).singleResult(); System.out.println("实例二当前任务:" + pInstance2Task.getName()); //发送合同变更信号 runtimeService.signalEventReceived("change"); //根据流程定义查询任务 List<Task> list = taskService.createTaskQuery().processDefinitionId(processDefinition.getId()).list(); list.forEach(task -> System.out.println("流程实例id:" + task.getProcessInstanceId() + "----------------任务:" + task.getName())); processEngine.close(); System.exit(0);
- 查看结果
五、补偿边界事件
- 说明:补偿边界事件的触发有两种情况:1. 事务子流程被取消时,会触发事务子流程里面的补偿边界事件。2. 使用补偿中间事件来触发,需要时Throwing事件。
- bpmn图
- 流程xml
<process id="process" isClosed="false" name="process" processType="None"> <startEvent id="startEvent" name="startEvent"/> <serviceTask activiti:exclusive="true" id="transferOut" name="转出银行扣款" activiti:class="com.xjf.test.delegate.TransferOutDelegate"/> <boundaryEvent attachedToRef="transferOut" cancelActivity="true" id="transferOutBoundary"> <compensateEventDefinition id="transferOutBoundary_ED_1" waitForCompletion="true"/> </boundaryEvent> <!--isForCompensation需要指明是补偿事件--> <serviceTask activiti:exclusive="true" id="transferOutCancel" name="转出银行取消" activiti:class="com.xjf.test.delegate.TransferOutCancelDelegate" isForCompensation="true"/> <serviceTask activiti:exclusive="true" id="transferIn" name="转入银行加款" activiti:class="com.xjf.test.delegate.TransferInDelegate"/> <boundaryEvent attachedToRef="transferIn" cancelActivity="true" id="transferInBoundary"> <compensateEventDefinition id="transferInBoundary_ED_1" waitForCompletion="true"/> </boundaryEvent> <serviceTask activiti:exclusive="true" id="transferInCancel" name="转入银行取消" activiti:class="com.xjf.test.delegate.TransferInCancelDelegate" isForCompensation="true"/> <sequenceFlow id="_2" sourceRef="startEvent" targetRef="transferOut"/> <sequenceFlow id="_3" sourceRef="transferOut" targetRef="transferIn"/> <serviceTask activiti:exclusive="true" id="verifyTransfer" name="验证转账结果" activiti:class="com.xjf.test.delegate.VerifyTransferDelegate"/> <boundaryEvent attachedToRef="verifyTransfer" cancelActivity="true" id="errorBoundary"> <errorEventDefinition errorRef="transferError" id="errorBoundary_ED_1"/> </boundaryEvent> <intermediateThrowEvent id="intermediateThrowEvent" name="NoneThrowEvent"> <compensateEventDefinition id="intermediateThrowEvent_ED_1" waitForCompletion="true"/> </intermediateThrowEvent> <endEvent id="normalEnd" name="正常结束"/> <endEvent id="compensateEnd" name="补偿结束"/> <sequenceFlow id="_4" sourceRef="transferIn" targetRef="verifyTransfer"/> <sequenceFlow id="_5" sourceRef="verifyTransfer" targetRef="normalEnd"/> <sequenceFlow id="_6" sourceRef="errorBoundary" targetRef="intermediateThrowEvent"/> <sequenceFlow id="_7" sourceRef="intermediateThrowEvent" targetRef="compensateEnd"/> <association associationDirection="None" id="a1" sourceRef="transferOutBoundary" targetRef="transferOutCancel"/> <association associationDirection="None" id="a2" sourceRef="transferInBoundary" targetRef="transferInCancel"/> </process>
对应的委托类:
public class TransferInCancelDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println("转入银行---取消增加金额");
}
}
public class TransferInDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println("转入银行---增加金额");
}
}
public class TransferOutCancelDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println("转出银行---取消扣减金额");
}
}
public class TransferOutDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
System.out.println("转出银行---扣减金额");
}
}
public class VerifyTransferDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
//从执行流中获取变量
boolean flag = (boolean)delegateExecution.getVariable("result");
if (flag){
System.out.println("转账成功");
}else {
System.out.println("转账失败,抛出错误");
throw new BpmnError("transferError");
}
}
}
- 编码发布
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); RuntimeService runtimeService = processEngine.getRuntimeService(); Deployment deployment = repositoryService.createDeployment().addClasspathResource("compensation-boundary-event.xml").deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult(); //存放变量,记录转账是否成功 Map<String,Object> vars = new HashMap<>(); vars.put("result",false); runtimeService.startProcessInstanceById(processDefinition.getId(), vars); processEngine.close(); System.exit(0);
- 查看结果
- 变量result=false:
- 变量result=true:
《疯狂Workflow讲义第二版》