BAEL-378 A Guide to Activiti with Java (#2245)

* Example Code For Evaluation Article

This is an example code for the evaluation article on "Different Types of Bean Injection in Spring"

* Added unit tests

* Minor changes to application context

* Removed code committed for evaluation article

* BAEL-944 Demonstrating the problems with new Url pattern matching in Spring 5

* BAEL-944 Demonstrating the problems with new Url pattern matching in Spring 5

* BAEL-944 Exploring the Spring MVC URL Matching Improvements

* BAEL-944 Exploring the Spring MVC URL Matching Improvements

* BAEL-944 Exploring the Spring MVC URL Matching Improvements

* BAEL-944 Code Formatting and solving build issue

* BAEL-944 Resolving build issue due to change in Spring version

* BAEL-944 Resolving build issue

* BAEL-944 Formatting code

* BAEL-944 Moving tests to correct package

* BAEL-944 Moving tests to correct package

* BAEL-944 Replacing @RequestMapping by @GetMapping

* BAEL-944 Remove unnecessary attribute name, "value" in annotations

* BAEL-79 Intro to Activiti with Spring

* BAEL-79 Intro to Activiti with Spring

* BAEL-79 Adding activiti module to the parent modules

* BAEL-79 Using latest version

* BAEL-79 Update Spring boot version that works with Activiti

* BAEL-79 Replace RequestMapping with GetMapping

* BAEL-79 Use Java 8 Syntax

* BAEL-79 Formatting

* BAEL-79 changed module name

* BAEL-378 A Guide to Activiti with Java

* BAEL-79 Fixed unit tests

* BAEL-79 Simplified the process

* BAEL-79 Fix test cases
This commit is contained in:
Mansi 2017-08-07 12:16:40 +05:30 committed by Grzegorz Piwowarek
parent ddee04fca6
commit a1388b643b
9 changed files with 388 additions and 62 deletions

View File

@ -42,16 +42,11 @@ public class ActivitiController {
} }
@GetMapping("/complete-task-A/{processInstanceId}") @GetMapping("/complete-task-A/{processInstanceId}")
public TaskRepresentation completeTaskA(@PathVariable String processInstanceId) { public void completeTaskA(@PathVariable String processInstanceId) {
Task task = taskService.createTaskQuery() Task task = taskService.createTaskQuery()
.processInstanceId(processInstanceId) .processInstanceId(processInstanceId)
.singleResult(); .singleResult();
taskService.complete(task.getId()); taskService.complete(task.getId());
logger.info("Task completed"); logger.info("Task completed");
task = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.singleResult();
return new TaskRepresentation(task.getId(), task.getName(), task.getProcessInstanceId());
} }
} }

View File

@ -0,0 +1,12 @@
package com.example.activitiwithspring.servicetasks;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
public class SendEmailServiceTask implements JavaDelegate {
public void execute(DelegateExecution execution) {
//logic to sent email confirmation
}
}

View File

@ -1,66 +1,35 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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/processdef" xmlns:modeler="http://activiti.com/modeler" modeler:version="1.0ev" modeler:exportDateTime="20170726123124" modeler:modelId="1005315" modeler:modelVersion="1" modeler:modelLastUpdated="1501068675875">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" <process id="my-process" name="say-hello-process" isExecutable="true">
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/processdef" xmlns:modeler="http://activiti.com/modeler"
modeler:version="1.0ev" modeler:exportDateTime="20170619132653"
modeler:modelId="1005315" modeler:modelVersion="1"
modeler:modelLastUpdated="1497875208422">
<process id="my-process" name="my-process"
isExecutable="true">
<startEvent id="startEvent" name="startEvent"> <startEvent id="startEvent" name="startEvent">
</startEvent> </startEvent>
<sequenceFlow id="sid-1A81F784-4743-4CD6-B81D-A6F61DFBDAF4" <sequenceFlow id="sequence-flow-1" sourceRef="startEvent" targetRef="A">
sourceRef="startEvent" targetRef="sid-293091EF-68C4-4A5C-B747-B1C46809CB69">
</sequenceFlow> </sequenceFlow>
<userTask id="sid-293091EF-68C4-4A5C-B747-B1C46809CB69" name="A" <userTask id="A" name="A" activiti:assignee="$INITIATOR">
activiti:assignee="$INITIATOR">
</userTask> </userTask>
<sequenceFlow id="sid-EA5C6B84-3FF8-4B39-8961-92F1E230F3FB" <sequenceFlow id="sequence-flow-2" sourceRef="A" targetRef="endEvent">
sourceRef="sid-293091EF-68C4-4A5C-B747-B1C46809CB69" targetRef="sid-7EAE076A-BCD0-416E-98E2-23A7E37C4010">
</sequenceFlow>
<userTask id="sid-7EAE076A-BCD0-416E-98E2-23A7E37C4010" name="B"
activiti:assignee="$INITIATOR">
</userTask>
<sequenceFlow id="sid-CB9C412E-AD0B-4EFA-B160-E1DA2507A3D9"
sourceRef="sid-7EAE076A-BCD0-416E-98E2-23A7E37C4010" targetRef="endEvent">
</sequenceFlow> </sequenceFlow>
<endEvent id="endEvent" name="endEvent"> <endEvent id="endEvent" name="endEvent">
</endEvent> </endEvent>
</process> </process>
<bpmndi:BPMNDiagram id="BPMNDiagram_say-hello-process"> <bpmndi:BPMNDiagram id="BPMNDiagram_say-hello-process">
<bpmndi:BPMNPlane bpmnElement="say-hello-process" <bpmndi:BPMNPlane bpmnElement="say-hello-process" id="BPMNPlane_say-hello-process">
id="BPMNPlane_say-hello-process">
<bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent"> <bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent">
<omgdc:Bounds height="30.0" width="30.0" x="120.0" y="163.0" /> <omgdc:Bounds height="30.0" width="30.0" x="120.0" y="163.0"/>
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endEvent" id="BPMNShape_endEvent"> <bpmndi:BPMNShape bpmnElement="endEvent" id="BPMNShape_endEvent">
<omgdc:Bounds height="28.0" width="28.0" x="525.0" y="164.0" /> <omgdc:Bounds height="28.0" width="28.0" x="365.0" y="164.0"/>
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-293091EF-68C4-4A5C-B747-B1C46809CB69" <bpmndi:BPMNShape bpmnElement="A" id="BPMNShape_A">
id="BPMNShape_sid-293091EF-68C4-4A5C-B747-B1C46809CB69"> <omgdc:Bounds height="80.0" width="100.0" x="210.0" y="138.0"/>
<omgdc:Bounds height="80.0" width="100.0" x="210.0" y="138.0" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-7EAE076A-BCD0-416E-98E2-23A7E37C4010" <bpmndi:BPMNEdge bpmnElement="sequence-flow-1" id="BPMNEdge_sequence-flow-1">
id="BPMNShape_sid-7EAE076A-BCD0-416E-98E2-23A7E37C4010"> <omgdi:waypoint x="150.0" y="178.0"/>
<omgdc:Bounds height="80.0" width="100.0" x="360.0" y="138.0" /> <omgdi:waypoint x="210.0" y="178.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-CB9C412E-AD0B-4EFA-B160-E1DA2507A3D9"
id="BPMNEdge_sid-CB9C412E-AD0B-4EFA-B160-E1DA2507A3D9">
<omgdi:waypoint x="460.0" y="178.0" />
<omgdi:waypoint x="525.0" y="178.0" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-EA5C6B84-3FF8-4B39-8961-92F1E230F3FB" <bpmndi:BPMNEdge bpmnElement="sequence-flow-2" id="BPMNEdge_sequence-flow-2">
id="BPMNEdge_sid-EA5C6B84-3FF8-4B39-8961-92F1E230F3FB"> <omgdi:waypoint x="310.0" y="178.0"/>
<omgdi:waypoint x="310.0" y="178.0" /> <omgdi:waypoint x="365.0" y="178.0"/>
<omgdi:waypoint x="360.0" y="178.0" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-1A81F784-4743-4CD6-B81D-A6F61DFBDAF4"
id="BPMNEdge_sid-1A81F784-4743-4CD6-B81D-A6F61DFBDAF4">
<omgdi:waypoint x="150.0" y="178.0" />
<omgdi:waypoint x="210.0" y="178.0" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </bpmndi:BPMNDiagram>

View File

@ -106,14 +106,12 @@ public class ActivitiControllerIntegrationTest {
.get(0); .get(0);
logger.info("process instance = " + pi.getId()); logger.info("process instance = " + pi.getId());
String responseBody = this.mockMvc.perform(MockMvcRequestBuilders.get("/complete-task-A/" + pi.getId())) this.mockMvc.perform(MockMvcRequestBuilders.get("/complete-task-A/" + pi.getId()))
.andReturn() .andReturn()
.getResponse() .getResponse()
.getContentAsString(); .getContentAsString();
ObjectMapper mapper = new ObjectMapper(); List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
TaskRepresentation task = mapper.readValue(responseBody, TaskRepresentation.class); assertEquals(0, list.size());
assertEquals("B", task.getName());
} }
} }

View File

@ -0,0 +1,64 @@
package com.example.activitiwithspring;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
public class ProcessEngineCreationTests {
@Test
public void givenXMLConfig_whenGetDefault_thenGotProcessEngine() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
assertNotNull(processEngine);
assertEquals("root", processEngine.getProcessEngineConfiguration().getJdbcUsername());
}
@Test
public void givenXMLConfig_whenCreateDefaultConfiguration_thenGotProcessEngine() {
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault();
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
assertNotNull(processEngine);
assertEquals("root", processEngine.getProcessEngineConfiguration().getJdbcUsername());
}
@Test
public void givenDifferentNameXMLConfig_whenGetProcessEngineConfig_thenGotResult() {
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("my.activiti.cfg.xml");
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
assertNotNull(processEngine);
assertEquals("baeldung", processEngine.getProcessEngineConfiguration().getJdbcUsername());
}
@Test
public void givenDifferentBeanNameInXMLConfig_whenGetProcessEngineConfig_thenGotResult() {
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResource("my.activiti.cfg.xml", "myProcessEngineConfiguration");
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
assertNotNull(processEngine);
assertEquals("baeldung", processEngine.getProcessEngineConfiguration().getJdbcUsername());
}
@Test
public void givenNoXMLConfig_whenCreateInMemProcessEngineConfig_thenCreated() {
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();
ProcessEngine processEngine = processEngineConfiguration
.setJdbcUrl("jdbc:h2:mem:my-own-in-mem-db;DB_CLOSE_DELAY=1000")
.buildProcessEngine();
assertNotNull(processEngine);
assertEquals("sa", processEngine.getProcessEngineConfiguration().getJdbcUsername());
}
@Test
public void givenNoXMLConfig_whenCreateProcessEngineConfig_thenCreated() {
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
ProcessEngine processEngine = processEngineConfiguration
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
.setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
.buildProcessEngine();
assertNotNull(processEngine);
assertEquals("sa", processEngine.getProcessEngineConfiguration().getJdbcUsername());
}
}

View File

@ -0,0 +1,97 @@
package com.example.activitiwithspring;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ProcessExecutionTests {
@Test
public void givenBPMN_whenDeployProcess_thenDeployed() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml")
.deploy();
Long count = repositoryService.createProcessDefinitionQuery().count();
assertTrue(count >= 1);
}
@Test
public void givenProcessDefinition_whenStartProcessInstance_thenProcessRunning() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml")
.deploy();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("vacationMotivation", "I'm really tired!");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("vacationRequest", variables);
Long count = runtimeService.createProcessInstanceQuery().count();
assertTrue(count >= 1);
}
@Test
public void givenProcessInstance_whenCompleteTask_thenProcessExecutionContinues() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml")
.deploy();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("vacationMotivation", "I'm really tired!");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("vacationRequest", variables);
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
Task task = tasks.get(0);
Map<String, Object> taskVariables = new HashMap<String, Object>();
taskVariables.put("vacationApproved", "false");
taskVariables.put("comments", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);
Task currentTask = taskService.createTaskQuery().taskName("Modify vacation request").singleResult();
assertNotNull(currentTask);
}
@Test(expected = ActivitiException.class)
public void givenProcessDefinition_whenSuspend_thenNoProcessInstanceCreated() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/vacationRequest.bpmn20.xml")
.deploy();
RuntimeService runtimeService = processEngine.getRuntimeService();
repositoryService.suspendProcessDefinitionByKey("vacationRequest");
runtimeService.startProcessInstanceByKey("vacationRequest");
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="" />
<property name="databaseSchemaUpdate" value="true" />
</bean>
</beans>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:baeldung;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="baeldung" />
<property name="jdbcPassword" value="" />
<property name="databaseSchemaUpdate" value="true" />
</bean>
<bean id="myProcessEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:baeldung;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="baeldung" />
<property name="jdbcPassword" value="" />
<property name="databaseSchemaUpdate" value="true" />
</bean>
</beans>

View File

@ -0,0 +1,149 @@
<?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:xsd="http://www.w3.org/2001/XMLSchema" 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/processdef" xmlns:modeler="http://activiti.com/modeler" modeler:version="1.0ev" modeler:exportDateTime="20170708124328" modeler:modelId="1005826" modeler:modelVersion="1" modeler:modelLastUpdated="1499514116825">
<process id="vacationRequest" name="vacationRequest" isExecutable="true">
<startEvent id="startEvent" name="request" activiti:initiator="employeeName">
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" type="long" required="true"/>
<activiti:formProperty id="startDate" name="Vacation start date (MM-dd-yyyy)" type="date" datePattern="MM-dd-yyyy hh:mm" required="true"/>
<activiti:formProperty id="reason" name="Reason for leave" type="string"/>
<modeler:editor-resource-id><![CDATA[startEvent1]]></modeler:editor-resource-id>
</extensionElements>
</startEvent>
<userTask id="handle_vacation_request" name="Handle Request for Vacation">
<documentation>${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${reason}).</documentation>
<extensionElements>
<activiti:formProperty id="vacationApproval" name="Do you approve this vacation request?" type="enum" required="true"/>
<activiti:formProperty id="comments" name="Comments from Manager" type="string"/>
<modeler:allow-send-email><![CDATA[true]]></modeler:allow-send-email>
<modeler:activiti-idm-initiator><![CDATA[true]]></modeler:activiti-idm-initiator>
<modeler:editor-resource-id><![CDATA[sid-B9AA8E66-2F11-45D0-A270-B052E1A9248E]]></modeler:editor-resource-id>
</extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<exclusiveGateway id="sid-12A577AE-5227-4918-8DE1-DC077D70967C">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-12A577AE-5227-4918-8DE1-DC077D70967C]]></modeler:editor-resource-id>
</extensionElements>
</exclusiveGateway>
<userTask id="modify_vacation_request" name="Modify vacation request" activiti:assignee="$INITIATOR">
<documentation>Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${comments}</documentation>
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" type="long" expression="${numberOfDays}" required="true"/>
<activiti:formProperty id="startDate" name="First day of vacation(MM-dd-yyyy)" type="date" expression="${startDate}" datePattern="MM-dd-yyyy hh:mm" required="true"/>
<activiti:formProperty id="reason" name="Reason for leave" type="string" expression="${reason}"/>
<activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true"/>
<modeler:allow-send-email><![CDATA[true]]></modeler:allow-send-email>
<modeler:activiti-idm-initiator><![CDATA[true]]></modeler:activiti-idm-initiator>
<modeler:initiator-can-complete><![CDATA[false]]></modeler:initiator-can-complete>
<modeler:editor-resource-id><![CDATA[sid-47240E94-C0C1-4886-B856-BC8E757746C9]]></modeler:editor-resource-id>
</extensionElements>
</userTask>
<serviceTask id="send-email-confirmation" name="Send email confirmation" activiti:class="com.example.activitiwithspring.servicetasks.SendEmailServiceTask.java">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-2C5E1831-9101-4F70-9AEF-4BA72B704205]]></modeler:editor-resource-id>
</extensionElements>
</serviceTask>
<sequenceFlow id="flow1" name="flow1" sourceRef="startEvent" targetRef="handle_vacation_request">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-638FA42C-E698-4BC9-9EB3-265968CA4E93]]></modeler:editor-resource-id>
</extensionElements>
</sequenceFlow>
<sequenceFlow id="flow2" name="flow2" sourceRef="handle_vacation_request" targetRef="sid-12A577AE-5227-4918-8DE1-DC077D70967C">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-6F2DDE04-7618-4EEA-B7DC-5BD5E0036BE3]]></modeler:editor-resource-id>
</extensionElements>
</sequenceFlow>
<endEvent id="EndEvent" name="End Event">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-381E38DD-C43B-4D36-8BB1-4C96F4E90A5C]]></modeler:editor-resource-id>
</extensionElements>
</endEvent>
<sequenceFlow id="flow7" name="flow7" sourceRef="send-email-confirmation" targetRef="EndEvent">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-F059DECE-ADF0-4BFC-BCB5-1F670ECA2C1D]]></modeler:editor-resource-id>
</extensionElements>
</sequenceFlow>
<sequenceFlow id="flow3" name="approved" sourceRef="sid-12A577AE-5227-4918-8DE1-DC077D70967C" targetRef="send-email-confirmation">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-609BEB69-E833-4D2F-BD14-FC8F7FD3E9C7]]></modeler:editor-resource-id>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${vacationApproved == 'true'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" name="rejected" sourceRef="sid-12A577AE-5227-4918-8DE1-DC077D70967C" targetRef="modify_vacation_request">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-C5D24BF7-A499-4B44-8670-F4D674475623]]></modeler:editor-resource-id>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${vacationApproved == 'false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow6" name="Don't Resend" sourceRef="modify_vacation_request" targetRef="EndEvent">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-5E626939-310D-4A58-947E-B3AE0DCDEE58]]></modeler:editor-resource-id>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${resendRequest == 'false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow5" name="Resend Request" sourceRef="modify_vacation_request" targetRef="handle_vacation_request">
<extensionElements>
<modeler:editor-resource-id><![CDATA[sid-F0B813CA-C242-4C33-861A-5EFDDAE0C66D]]></modeler:editor-resource-id>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${resendRequest == 'true'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_vacationRequest">
<bpmndi:BPMNPlane bpmnElement="vacationRequest" id="BPMNPlane_vacationRequest">
<bpmndi:BPMNShape bpmnElement="startEvent" id="BPMNShape_startEvent">
<omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="handle_vacation_request" id="BPMNShape_handle_vacation_request">
<omgdc:Bounds height="80.0" width="100.0" x="210.0" y="138.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-12A577AE-5227-4918-8DE1-DC077D70967C" id="BPMNShape_sid-12A577AE-5227-4918-8DE1-DC077D70967C">
<omgdc:Bounds height="40.0" width="40.0" x="375.0" y="158.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="modify_vacation_request" id="BPMNShape_modify_vacation_request">
<omgdc:Bounds height="80.0" width="100.0" x="465.0" y="225.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="send-email-confirmation" id="BPMNShape_send-email-confirmation">
<omgdc:Bounds height="80.0" width="100.0" x="465.0" y="105.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="EndEvent" id="BPMNShape_EndEvent">
<omgdc:Bounds height="28.0" width="28.0" x="660.0" y="180.0"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="130.0" y="178.0"/>
<omgdi:waypoint x="210.0" y="178.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="310.0" y="178.18450184501845"/>
<omgdi:waypoint x="375.4259259259259" y="178.42592592592592"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="411.12091503267976" y="174.12091503267973"/>
<omgdi:waypoint x="465.0" y="159.01673640167365"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="395.5" y="197.5"/>
<omgdi:waypoint x="395.5" y="265.0"/>
<omgdi:waypoint x="465.0" y="265.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="465.0" y="285.0"/>
<omgdi:waypoint x="259.75" y="285.0"/>
<omgdi:waypoint x="259.99632352941177" y="218.0"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
<omgdi:waypoint x="565.0" y="242.67295597484278"/>
<omgdi:waypoint x="661.2166041257227" y="199.70830884952008"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
<omgdi:waypoint x="565.0" y="145.0"/>
<omgdi:waypoint x="674.0" y="145.0"/>
<omgdi:waypoint x="674.0" y="180.0"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>