https://blog.csdn.net/fanxiangru999/article/details/79381966
前兩天做了一個SpringBoot整合Activiti的完整示例,功能包括:退回/通過(節點條件)、指定辦理人、生成流程圖、高亮顯示已辦節點、查詢任務清單(辦理人)等,下面先簡單記錄(含完整代碼),十六上班後再詳細補充。
1、畫流程圖:
高亮生成的流程圖(流程已至辦理):
這個流程圖比較簡單,這裡不介紹如何畫的了(記得讓檔案名稱與id相同),下面有最終的流程圖源碼。
2、設定業戶送出、資料不全、已簽發的事件觸發代碼:
點選選擇事件節點,下方properties裡選擇如下圖:
找不到properties的話 要選擇Activiti模式就可以:
#{activityDemoServiceImpl.updateBizStatus(execution,"tj")} 表示将使用activityDemoServiceImpl服務的updateBizStatus方法,裡面有兩個參數,execution是目前流程節點對象,可擷取流程資訊及業務key等,"tj"字元串參數。(這裡設定的服務名是小寫開頭,實際服務名是大寫開頭,否則找不到——不知道是不是因為我用的5.22)
3、指定受理/審批 辦理人員:
也是選中,然後如下圖操作:
${activityDemoServiceImpl.findUsersForSL(execution)}跟上面一樣,不過注意,事件監聽是以#開頭,這裡是以$符号。
4、增加2、3設定的服務方法(ActivityDemoServiceImpl)
SpringBoot的好處是預設會配置和注入很多服務,是以我們使用起來非常友善,流程圖不需要單獨部署,直接到服務根據流程名稱或id就可以直接擷取到想要的内容。
直接上代碼了:
package com.example.service.impl;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ActivityDemoServiceImpl {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessEngineConfigurationImpl processEngineConfiguration;
public void startProcesses(String bizId) {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo5", bizId);//流程圖id,業務表id
System.out.println("流程啟動成功,流程id:"+pi.getId());
}
public List<Task> findTasksByUserId(String userId) {
List<Task> resultTask = taskService.createTaskQuery().processDefinitionKey("demo5").taskCandidateOrAssigned(userId).list();
return resultTask;
}
public void completeTask(String taskId,String userId,String result) {
//擷取流程執行個體
taskService.claim(taskId, userId);
Map<String,Object> vars = new HashMap<String,Object>();
vars.put("sign", "true");
taskService.complete(taskId, vars);
}
public void updateBizStatus(DelegateExecution execution,String status) {
String bizId = execution.getProcessBusinessKey();
//根據業務id自行處理業務表
System.out.println("業務表["+bizId+"]狀态更改成功,狀态更改為:"+status);
}
//流程節點權限使用者清單${ActivityDemoServiceImpl.findUsers(execution,sign)}
public List<String> findUsersForSL(DelegateExecution execution){
return Arrays.asList("sly1","sly2");
}
//流程節點權限使用者清單${ActivityDemoServiceImpl.findUsers(execution,sign)}
public List<String> findUsersForSP(DelegateExecution execution){
return Arrays.asList("spy1","uspy2");
}
public void queryProImg(String processInstanceId) throws Exception {
//擷取曆史流程執行個體
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//根據流程定義擷取輸入流
InputStream is = repositoryService.getProcessDiagram(processInstance.getProcessDefinitionId());
BufferedImage bi = ImageIO.read(is);
File file = new File("demo2.png");
if(!file.exists()) file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write(bi, "png", fos);
fos.close();
is.close();
System.out.println("圖檔生成成功");
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("userId").list();
for(Task t : tasks) {
System.out.println(t.getName());
}
}
public void queryProHighLighted(String processInstanceId) throws Exception {
//擷取曆史流程執行個體
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
//擷取流程圖
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
//高亮環節id集合
List<String> highLightedActivitis = new ArrayList<String>();
//高亮線路id集合
List<String> highLightedFlows = getHighLightedFlows(definitionEntity,highLightedActivitList);
for(HistoricActivityInstance tempActivity : highLightedActivitList){
String activityId = tempActivity.getActivityId();
highLightedActivitis.add(activityId);
}
//配置字型
InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitis, highLightedFlows,"宋體","微軟雅黑","黑體",null,2.0);
BufferedImage bi = ImageIO.read(imageStream);
File file = new File("demo2.png");
if(!file.exists()) file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write(bi, "png", fos);
fos.close();
imageStream.close();
System.out.println("圖檔生成成功");
}
private List<String> getHighLightedFlows(
ProcessDefinitionEntity processDefinitionEntity,
List<HistoricActivityInstance> historicActivityInstances) {
List<String> highFlows = new ArrayList<String>();// 用以儲存高亮的線flowId
for (int i = 0; i < historicActivityInstances.size() - 1; i++) {// 對曆史流程節點進行周遊
ActivityImpl activityImpl = processDefinitionEntity
.findActivity(historicActivityInstances.get(i)
.getActivityId());// 得到節點定義的詳細資訊
List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();// 用以儲存後需開始時間相同的節點
ActivityImpl sameActivityImpl1 = processDefinitionEntity
.findActivity(historicActivityInstances.get(i + 1)
.getActivityId());
// 将後面第一個節點放在時間相同節點的集合裡
sameStartTimeNodes.add(sameActivityImpl1);
for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
HistoricActivityInstance activityImpl1 = historicActivityInstances
.get(j);// 後續第一個節點
HistoricActivityInstance activityImpl2 = historicActivityInstances
.get(j + 1);// 後續第二個節點
if (activityImpl1.getStartTime().equals(
activityImpl2.getStartTime())) {
// 如果第一個節點和第二個節點開始時間相同儲存
ActivityImpl sameActivityImpl2 = processDefinitionEntity
.findActivity(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
} else {
// 有不相同跳出循環
break;
}
}
List<PvmTransition> pvmTransitions = activityImpl
.getOutgoingTransitions();// 取出節點的所有出去的線
for (PvmTransition pvmTransition : pvmTransitions) {
// 對所有的線進行周遊
ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition
.getDestination();
// 如果取出的線的目标節點存在時間相同的節點裡,儲存該線的id,進行高亮顯示
if (sameStartTimeNodes.contains(pvmActivityImpl)) {
highFlows.add(pvmTransition.getId());
}
}
}
return highFlows;
}
}
5、測試:(ActivitiDemoTest)
package com.example.test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import org.activiti.engine.HistoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricDetail;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.example.Application;
import com.example.entity.Person;
import com.example.service.impl.ActivityDemoServiceImpl;
//這是JUnit的注解,通過這個注解讓SpringJUnit4ClassRunner這個類提供Spring測試上下文。
@RunWith(SpringJUnit4ClassRunner.class)
//這是Spring Boot注解,為了進行內建測試,需要通過這個注解加載和配置Spring應用上下
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class ActivitiDemoTest {
@Resource
private ActivityDemoServiceImpl activityDemoServiceImpl;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
//啟動流程---215001
@Test
public void startPro() {
activityDemoServiceImpl.startProcesses("123456");
}
//擷取受理員任務清單
@Test
public void findTasksForSL() {
List<Task> lists = activityDemoServiceImpl.findTasksByUserId("sly1");
System.out.println("任務清單:"+lists);//任務清單:[Task[id=210028, name=受理], Task[id=215005, name=受理]]
}
//受理員受理資料
@Test
public void completeTasksForSL() {
activityDemoServiceImpl.completeTask("210028", "sly1", "true");//受理後,任務清單資料減少
}
//擷取審批員任務清單
@Test
public void findTasksForSP() {
List<Task> lists = activityDemoServiceImpl.findTasksByUserId("spy1");
System.out.println("任務清單:"+lists);//任務清單:[Task[id=220004, name=審批]]
}
//審批員通過稽核
@Test
public void completeTasksForSP() {
activityDemoServiceImpl.completeTask("220004", "spy1", "true");//審批後,任務清單資料減少
}
//設定流程變量
//設定流程變量【基本類型】
@Test
public void setTasksVar() {
List<Task> lists = activityDemoServiceImpl.findTasksByUserId("sly1");
for(Task task : lists) {//不知為何,變量儲存成功,但資料表隻有請假天數含有任務id,單擷取流程變量時,根據任務id均可擷取到(如下一測試)
taskService.setVariable(task.getId(), "請假人", "sly1");
taskService.setVariableLocal(task.getId(), "請假天數",3);
taskService.setVariable(task.getId(), "請假日期", new Date());
}
}
//擷取流程變量
@Test
public void getTasksVar() {
List<Task> lists = activityDemoServiceImpl.findTasksByUserId("sly1");
for(Task task : lists) {
//擷取流程變量【基本類型】
String person = (String) taskService.getVariable(task.getId(), "請假人");
Integer day = (Integer) taskService.getVariableLocal(task.getId(), "請假天數");
Date date = (Date) taskService.getVariable(task.getId(), "請假日期");
System.out.println("流程變量:"+person+"||"+day+"||"+date+"||");
}
}
//設定流程變量【實體】
@Test
public void setTasksVarEntity() {
List<Task> lists = activityDemoServiceImpl.findTasksByUserId("sly1");
for(Task task : lists) {
Person p = new Person();
p.setName("翠花");
p.setId(20);
p.setDate();;
p.setNote("回去探親,一起吃個飯123");
taskService.setVariable(task.getId(), "人員資訊(添加強定版本)", p);
System.out.println("設定流程變量成功!");
}
}
//擷取流程變量【實體】 實體必須序列化
@Test
public void getTasksVarEntity() {
List<Task> lists = activityDemoServiceImpl.findTasksByUserId("sly1");
for(Task task : lists) {
// 2.擷取流程變量,使用javaBean類型
Person p = (Person)taskService.getVariable(task.getId(), "人員資訊(添加強定版本)");
System.out.println(" 請假人: "+p.getName()+" 請假天數: "+p.getId()+" 請假時間:"+ p.getDate()+ " 請假原因: "+p.getNote());
}
}
//生成流程圖---232501
@Test
public void queryProImg() throws Exception {
activityDemoServiceImpl.queryProImg("232501");
}
//生成流程圖(高亮)---232501
@Test
public void queryProHighLighted() throws Exception {
activityDemoServiceImpl.queryProHighLighted("232501");
}
@Test
public void findHistoryProcessVariables(){
List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery()//建立一個曆史的流程變量查詢對象
.variableName("請假天數")
.list();
if (list!=null &&list.size()>0) {
for (HistoricVariableInstance hvi : list) {
System.out.println(hvi.getId()+" "+hvi.getProcessInstanceId()+" "+hvi.getVariableName()
+" "+hvi.getVariableTypeName()+" "+hvi.getValue());
System.out.println("########################################");
}
}
}
@Test
public void findHistoricProcessInstance() {
// 查詢已完成的流程
List<HistoricProcessInstance> datas = historyService
.createHistoricProcessInstanceQuery().finished().list();
System.out.println("使用finished方法:" + datas.size());
// 根據流程定義ID查詢
datas = historyService.createHistoricProcessInstanceQuery()
.processDefinitionId("processDefinitionId").list();
System.out.println("使用processDefinitionId方法: " + datas.size());
// 根據流程定義key(流程描述檔案的process節點id屬性)查詢
datas = historyService.createHistoricProcessInstanceQuery()
.processDefinitionKey("processDefinitionKey").list();
System.out.println("使用processDefinitionKey方法: " + datas.size());
// 根據業務主鍵查詢
datas = historyService.createHistoricProcessInstanceQuery()
.processInstanceBusinessKey("processInstanceBusinessKey").list();
System.out.println("使用processInstanceBusinessKey方法: " + datas.size());
// 根據流程執行個體ID查詢
datas = historyService.createHistoricProcessInstanceQuery()
.processInstanceId("processInstanceId").list();
System.out.println("使用processInstanceId方法: " + datas.size());
// 查詢沒有完成的流程執行個體
historyService.createHistoricProcessInstanceQuery().unfinished().list();
System.out.println("使用unfinished方法: " + datas.size());
}
@Test
public void findHistoricTasks() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//曆史資料查詢
List<HistoricTaskInstance> datas = historyService.createHistoricTaskInstanceQuery()
.finished().list();
System.out.println("使用finished方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.processDefinitionId("processDefinitionId").list();
System.out.println("使用processDefinitionId方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.processDefinitionKey("testProcess").list();
System.out.println("使用processDefinitionKey方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.processDefinitionName("testProcess2").list();
System.out.println("使用processDefinitionName方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.processFinished().list();
System.out.println("使用processFinished方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.processInstanceId("processInstanceId").list();
System.out.println("使用processInstanceId方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.processUnfinished().list();
System.out.println("使用processUnfinished方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.taskAssignee("crazyit").list();
System.out.println("使用taskAssignee方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.taskAssigneeLike("%zy%").list();
System.out.println("使用taskAssigneeLike方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.taskDefinitionKey("usertask1").list();
System.out.println("使用taskDefinitionKey方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.taskDueAfter(sdf.parse("2020-10-11 06:00:00")).list();
System.out.println("使用taskDueAfter方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.taskDueBefore(sdf.parse("2022-10-11 06:00:00")).list();
System.out.println("使用taskDueBefore方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.taskDueDate(sdf.parse("2020-10-11 06:00:00")).list();
System.out.println("使用taskDueDate方法查詢:" + datas.size());
datas = historyService.createHistoricTaskInstanceQuery()
.unfinished().list();
System.out.println("使用unfinished方法查詢:" + datas.size());
}
@Test
public void findHistoricActivityInstance() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//查詢資料
List<HistoricActivityInstance> datas = historyService.createHistoricActivityInstanceQuery()
.activityId("endevent1").list();
System.out.println("使用activityId查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery()
.activityInstanceId(datas.get(0).getId()).list();
System.out.println("使用activityInstanceId查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery()
.activityType("intermediateSignalCatch").list();
System.out.println("使用activityType查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery()
.executionId("executionId").list();
System.out.println("使用executionId查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery().finished().list();
System.out.println("使用finished查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery()
.processInstanceId("processInstanceId").list();
System.out.println("使用processInstanceId查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery()
.taskAssignee("crazyit").list();
System.out.println("使用taskAssignee查詢:" + datas.size());
datas = historyService.createHistoricActivityInstanceQuery().unfinished().list();
System.out.println("使用unfinished查詢:" + datas.size());
}
@Test
public void findHistoricDetail() {
// 查詢曆史行為
HistoricActivityInstance act = historyService.createHistoricActivityInstanceQuery()
.activityName("First Task").finished().singleResult();
List<HistoricDetail> datas = historyService.createHistoricDetailQuery()
.activityInstanceId(act.getId()).list();
System.out.println("使用activityInstanceId方法查詢:" + datas.size());
datas = historyService.createHistoricDetailQuery().excludeTaskDetails().list();
System.out.println("使用excludeTaskDetails方法查詢:" + datas.size());
datas = historyService.createHistoricDetailQuery().formProperties().list();
System.out.println("使用formProperties方法查詢:" + datas.size());
datas = historyService.createHistoricDetailQuery().processInstanceId("processInstanceId").list();
System.out.println("使用processInstanceId方法查詢:" + datas.size());
datas = historyService.createHistoricDetailQuery().taskId("taskId").list();
System.out.println("使用taskId方法查詢:" + datas.size());
datas = historyService.createHistoricDetailQuery().variableUpdates().list();
System.out.println("使用variableUpdates方法查詢:" + datas.size());
}
}
流程圖源碼:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="demo5" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<serviceTask id="servicetask1" name="業戶送出" activiti:expression="#{activityDemoServiceImpl.updateBizStatus(execution,"tj")}"></serviceTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="servicetask1"></sequenceFlow>
<userTask id="usertask1" name="受理" activiti:candidateUsers="${activityDemoServiceImpl.findUsersForSL(execution)}"></userTask>
<sequenceFlow id="flow2" sourceRef="servicetask1" targetRef="usertask1"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow3" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow>
<userTask id="usertask2" name="審批" activiti:candidateUsers="${activityDemoServiceImpl.findUsersForSP(execution)}"></userTask>
<sequenceFlow id="flow4" sourceRef="exclusivegateway1" targetRef="usertask2"></sequenceFlow>
<serviceTask id="servicetask2" name="已簽發" activiti:expression="#{activityDemoServiceImpl.updateBizStatus(execution,"yqf")}"></serviceTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow6" sourceRef="servicetask2" targetRef="endevent1"></sequenceFlow>
<serviceTask id="servicetask3" name="資料不全" activiti:expression="#{activityDemoServiceImpl.updateBizStatus(execution,"zlbq")}"></serviceTask>
<sequenceFlow id="flow8" sourceRef="exclusivegateway1" targetRef="servicetask3">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${sign=="false"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow9" sourceRef="servicetask3" targetRef="endevent1"></sequenceFlow>
<exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow10" sourceRef="usertask2" targetRef="exclusivegateway2"></sequenceFlow>
<sequenceFlow id="flow11" sourceRef="exclusivegateway2" targetRef="servicetask2"></sequenceFlow>
<sequenceFlow id="flow12" sourceRef="exclusivegateway2" targetRef="servicetask3"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_demo5">
<bpmndi:BPMNPlane bpmnElement="demo5" id="BPMNPlane_demo5">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="-95.0" y="179.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="servicetask1" id="BPMNShape_servicetask1">
<omgdc:Bounds height="55.0" width="105.0" x="5.0" y="169.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="155.0" y="169.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="305.0" y="177.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="390.0" y="170.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="servicetask2" id="BPMNShape_servicetask2">
<omgdc:Bounds height="55.0" width="105.0" x="630.0" y="169.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="780.0" y="179.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="servicetask3" id="BPMNShape_servicetask3">
<omgdc:Bounds height="55.0" width="105.0" x="508.0" y="30.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="BPMNShape_exclusivegateway2">
<omgdc:Bounds height="40.0" width="40.0" x="540.0" y="177.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="-60.0" y="196.0"></omgdi:waypoint>
<omgdi:waypoint x="5.0" y="196.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="110.0" y="196.0"></omgdi:waypoint>
<omgdi:waypoint x="155.0" y="196.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="260.0" y="196.0"></omgdi:waypoint>
<omgdi:waypoint x="305.0" y="197.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="345.0" y="197.0"></omgdi:waypoint>
<omgdi:waypoint x="390.0" y="197.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
<omgdi:waypoint x="735.0" y="196.0"></omgdi:waypoint>
<omgdi:waypoint x="780.0" y="196.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
<omgdi:waypoint x="325.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="325.0" y="56.0"></omgdi:waypoint>
<omgdi:waypoint x="508.0" y="57.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
<omgdi:waypoint x="613.0" y="57.0"></omgdi:waypoint>
<omgdi:waypoint x="797.0" y="56.0"></omgdi:waypoint>
<omgdi:waypoint x="797.0" y="179.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
<omgdi:waypoint x="495.0" y="197.0"></omgdi:waypoint>
<omgdi:waypoint x="540.0" y="197.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
<omgdi:waypoint x="580.0" y="197.0"></omgdi:waypoint>
<omgdi:waypoint x="630.0" y="196.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow12" id="BPMNEdge_flow12">
<omgdi:waypoint x="560.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="560.0" y="85.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>