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

本人个人博客网站,欢迎访问:学教府

一、概述

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

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

二、定时器边界事件

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

三、错误边界事件

  1. 说明:当子流程中的ServiceTask抛出错误abc时,子流程的错误边界事件(定义错误引用为“abc”,没有具体的错误实现,则默认errorCode为引用的字符串“abc")会捕获该错误。 因此最终查询任务时是在ErrorTask

  2. bpmn图
    在这里插入图片描述

  3. 流程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);
    
  4. 编码发布

    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);
    
  5. 查看结果
    在这里插入图片描述

四、信号边界事件

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

五、补偿边界事件

  1. 说明:补偿边界事件的触发有两种情况:1. 事务子流程被取消时,会触发事务子流程里面的补偿边界事件。2. 使用补偿中间事件来触发,需要时Throwing事件。
  2. bpmn图
    在这里插入图片描述
  3. 流程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");
        }
    }
}
  1. 编码发布
    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);
    
  2. 查看结果
  • 变量result=false:
    在这里插入图片描述
  • 变量result=true:
    在这里插入图片描述

《疯狂Workflow讲义第二版》

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值