流程流转到一个普通任务时, 如果在指定时间内没有完成, 就会触发定时边界事件。
流程xml如下
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn" targetNamespace="Examples"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL
http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd">
<process id="boundaryEventFlow" name="定时边界事件">
<startEvent id="startEvent"/>
<userTask id="commonTask" name="Common Task"/>
<!-- 声明边界事件, attachedToRef 指定边界事件的起源 -->
<boundaryEvent id="boundaryEvent" name="Timer" attachedToRef="commonTask" cancelActivity="true">
<timerEventDefinition>
<!-- 在任务开始 5 秒之后触发, 如果commonTask中的任务还没有完成,就会触发边界事件,把流程走向Timeout Task -->
<timeDuration>PT5S</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<userTask id="timeoutTask" name="Timeout Task"/>
<endEvent id="end1"/>
<endEvent id="end2"/>
<sequenceFlow sourceRef="startEvent" targetRef="commonTask"/>
<sequenceFlow sourceRef="commonTask" targetRef="end1"/>
<sequenceFlow sourceRef="boundaryEvent" targetRef="timeoutTask"/>
<sequenceFlow sourceRef="timeoutTask" targetRef="end2"/>
</process>
</definitions>
一个流程触发,走到了Common Task,如果这个Common Task在5秒内没有完成走到end1,那么,就会触发事件边界事件,走到Timeout Task。代码示例:
package common;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.FileUtils;
public class ProcessEngineUtil {
public ProcessEngineConfiguration configuration;
public ProcessEngine processEngine;
public RepositoryService repositoryService;
public ProcessDefinition processDefinition;
public ProcessEngineUtil(String bpmnFile) {
configuration =
ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
processEngine = configuration.buildProcessEngine();
processEngine.getProcessEngineConfiguration().getAsyncExecutor().start();
repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource(bpmnFile)
.deploy();
String deploymentId = deployment.getId();
processDefinition = repositoryService.
createProcessDefinitionQuery().
deploymentId(deploymentId)
.singleResult();
}
public ProcessDefinition getProcessDefinition() {
return processDefinition;
}
public ProcessEngine getProcessEngine() {
return processEngine;
}
public void draw(ProcessInstance processInstance){
DefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new DefaultProcessDiagramGenerator(); // 创建默认的流程图生成器
String imageType = "png"; // 生成图片的类型
List<String> highLightedActivities = new ArrayList<>(); // 高亮节点集合
List<String> highLightedFlows = new ArrayList<>(); // 高亮连线集合
List<HistoricActivityInstance> hisActInsList = processEngine.getHistoryService().createHistoricActivityInstanceQuery()
.processInstanceId(processInstance.getProcessInstanceId())
.list(); // 查询所有历史节点信息
hisActInsList.forEach(historicActivityInstance -> { // 遍历
if("sequenceFlow".equals(historicActivityInstance.getActivityType())) {
// 添加高亮连线
highLightedFlows.add(historicActivityInstance.getActivityId());
} else {
// 添加高亮节点
highLightedActivities.add(historicActivityInstance.getActivityId());
}
});
String activityFontName = "宋体"; // 节点字体
String labelFontName = "微软雅黑"; // 连线标签字体
String annotationFontName = "宋体"; // 连线标签字体
ClassLoader customClassLoader = null; // 类加载器
double scaleFactor = 1.0d; // 比例因子,默认即可
boolean drawSequenceFlowNameWithNoLabelDI = true; // 不设置连线标签不会画
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(bpmnModel);
bpmnAutoLayout.setTaskHeight(120);
bpmnAutoLayout.setTaskWidth(120);
bpmnAutoLayout.execute();
InputStream
inputStream = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, imageType, highLightedActivities
, highLightedFlows, activityFontName, labelFontName, annotationFontName, customClassLoader,
scaleFactor); // 获取输入流
try {
// 先将图片保存
FileUtils.copyInputStreamToFile(inputStream, new File("1.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.lala.timerboundary;
import com.lala.hexo.DemoMain;
import common.ProcessEngineUtil;
import java.util.List;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TimerBoundary {
public static void main(String[] args)
throws InterruptedException {
ProcessEngineUtil processEngineUtil = new ProcessEngineUtil("boundaryEvent.bpmn20.xml");
ProcessEngine processEngine = processEngineUtil.getProcessEngine();
ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("boundaryEventFlow");
// task 列表
List<Task> beforeSleepTaskList = processEngine.getTaskService().createTaskQuery().list();
for (Task task : beforeSleepTaskList) {
System.out.println("休眠前 task.name = " + task.getName());
// processEngine.getTaskService().complete(task.getId());
}
// 强制睡眠等待边界事件触发
Thread.sleep(10 * 1000);
// task 列表
List<Task> afterSleepTaskList = processEngine.getTaskService().createTaskQuery().list();
System.out.println("休眠后 task 总数: " + afterSleepTaskList.size());
for (Task task : afterSleepTaskList) {
System.out.println("休眠后 task.name = " + task.getName());
}
processEngineUtil.draw(processInstance);
}
}
以上输出:
流程图如下:
ps。如果发现定时器失效,可能是没有加
processEngine.getProcessEngineConfiguration().getAsyncExecutor().start(); // 开启定时器
实例一:
如果把main函数中注释
processEngine.getTaskService().complete(task.getId());
那么,流程就不会走到Timeout Task中,输入会变成:
流程如下:
实例二:
如果代码改成:在休眠之后,再去触发完成common Task的事件
List<Task> beforeSleepTaskList = processEngine.getTaskService().createTaskQuery().list();
// 强制睡眠等待边界事件触发
Thread.sleep(10 * 1000);
for (Task task : beforeSleepTaskList) {
System.out.println("休眠后 task.name = " + task.getName());
processEngine.getTaskService().complete(task.getId());
}
就会抛出处理异常,以为这时流程已经走到了timeout Task了。