前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第十二节:Activiti6.0——四种边界事件:定时器、错误、信号、补偿

第十二节:Activiti6.0——四种边界事件:定时器、错误、信号、补偿

作者头像
凡人飞
发布2020-09-21 11:03:51
3.5K0
发布2020-09-21 11:03:51
举报
文章被收录于专栏:指缝阳光

一、概述

边界事件:边界事件属于一种特殊的中间事件。区别是: 中间事件 可以单独作为流程元素存在于流程中,而 边界事件 必须附属于某个流程元素(如任务、子流程等)。边界事件是Catching事件。

注意:补偿事件的连接线需要用association,association必须放在所有标签最后。

二、定时器边界事件

  1. 说明:定时器边界事件会在定时器时间到了之后进行触发,需要开启异步执行器(在activiti.cfg.xml中)。此处模拟一个损坏的物品首先交给初级工程师修理,定时1分钟后没有修好就给中级工程师修理
  2. 流程图
  1. 流程的xml
代码语言:javascript
复制
<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>
  1. 编码发布
代码语言:javascript
复制
 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);
  1. 查看结果

三、错误边界事件

  1. 说明:当子流程中的ServiceTask抛出错误abc时,子流程的错误边界事件(定义错误引用为“abc”,没有具体的错误实现,则默认errorCode为引用的字符串“abc")会捕获该错误。 因此最终查询任务时是在ErrorTask
  2. bpmn图
  1. 流程xml
代码语言:javascript
复制
<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>
  1. 委托类ThrowErrorDelegate:
代码语言:javascript
复制
String errorCode = "abc";
System.out.println("抛出错误:errorCode=" + errorCode);

throw new BpmnError(errorCode);
  1. 编码发布
代码语言:javascript
复制
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);
  1. 查看结果

四、信号边界事件

  1. 说明:该事件接收到指定的信号后触发,不同的是信号事件是全局的,即信号不是只在一个流程实例中传递,而是所有流程实例都是一样的(一处发信号,所有信号的边界事件都能接收)。此处测试的就是两个流程实例接收同一个信号。
  2. bpmn图
  1. 流程xml
代码语言:javascript
复制
<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>
  1. 编码发布
代码语言:javascript
复制
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. 查看结果

五、补偿边界事件

  1. 说明:补偿边界事件的触发有两种情况:1. 事务子流程被取消时,会触发事务子流程里面的补偿边界事件。2. 使用补偿中间事件来触发,需要时Throwing事件。
  2. bpmn图
  1. 流程xml
代码语言:javascript
复制
<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>
 

对应的委托类:

代码语言:javascript
复制
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");
        }
    }
}
  1. 编码发布
代码语言:javascript
复制
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);
  1. 查看结果
  • 变量result=false:
  • 变量result=true:

《疯狂Workflow讲义第二版》

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/12/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述
  • 二、定时器边界事件
  • 三、错误边界事件
  • 四、信号边界事件
  • 五、补偿边界事件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档