/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.test.bpmn.event.end;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.bpmn.model.ExtensionAttribute;
import org.activiti.bpmn.model.ExtensionElement;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.bpmn.behavior.TerminateEndEventActivityBehavior;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
/**
* @author Nico Rehwaldt
* @author Joram Barrez
*/
public class TerminateEndEventTest extends PluggableActivitiTestCase {
public static int serviceTaskInvokedCount = 0;
@Override
protected void setUp() throws Exception {
super.setUp();
serviceTaskInvokedCount = 0;
serviceTaskInvokedCount2 = 0;
}
public static class CountDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
serviceTaskInvokedCount++;
// leave only 3 out of n subprocesses
execution.setVariableLocal("terminate", serviceTaskInvokedCount > 3);
}
}
public static int serviceTaskInvokedCount2 = 0;
public static class CountDelegate2 implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
serviceTaskInvokedCount2++;
}
}
@Deployment
public void testProcessTerminate() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
long executionEntities = runtimeService.createExecutionQuery().processInstanceId(pi.getId()).count();
assertEquals(3, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateTask").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testProcessTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateTask").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateWithSubProcess() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// should terminate the process and
long executionEntities = runtimeService.createExecutionQuery().processInstanceId(pi.getId()).count();
assertEquals(4, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateWithSubProcess2() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// Completing the task -> terminal end event -> subprocess ends
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateEnd").singleResult();
assertNotNull(task);
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateWithSubProcessTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// Completing the task -> terminal end event -> all ends (termninate all)
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources={
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateWithCallActivity.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessNoTerminate.bpmn"
})
public void testTerminateWithCallActivity() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
long executionEntities = runtimeService.createExecutionQuery().processInstanceId(pi.getId()).count();
assertEquals(4, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources = {
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateWithCallActivityTerminateAll.bpmn20.xml",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessNoTerminate.bpmn" })
public void testTerminateWithCallActivityTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
Task task = taskService.createTaskQuery().processInstanceId(pi.getId())
.taskDefinitionKey("preTerminateEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources = {
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInExclusiveGatewayWithCallActivity.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessNoTerminate.bpmn"
})
public void testTerminateInExclusiveGatewayWithCallActivity() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample-terminateAfterExclusiveGateway");
long executionEntities = runtimeService.createExecutionQuery().processInstanceId(pi.getId()).count();
assertEquals(4, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateEnd").singleResult();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("input", 1);
taskService.complete(task.getId(), variables);
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInExclusiveGatewayWithMultiInstanceSubProcess() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample-terminateAfterExclusiveGateway");
long executionEntities = runtimeService.createExecutionQuery().processInstanceId(pi.getId()).count();
assertEquals(14, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateEnd").singleResult();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("input", 1);
taskService.complete(task.getId(), variables);
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInExclusiveGatewayWithMultiInstanceSubProcessTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample-terminateAfterExclusiveGateway");
// Completing the task once should only destroy ONE multi instance
List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("task").list();
assertEquals(5, tasks.size());
for (int i=0; i<5; i++) {
taskService.complete(tasks.get(i).getId());
assertTrue(runtimeService.createProcessInstanceQuery().processInstanceId(pi.getId()).count() > 0);
}
// Other task will now finish the process instance
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTerminateEnd").singleResult();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("input", 1);
taskService.complete(task.getId(), variables);
assertTrue(runtimeService.createProcessInstanceQuery().processInstanceId(pi.getId()).count() == 0);
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcess() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// should terminate the subprocess and continue the parent
long executionEntities = runtimeService.createExecutionQuery().processInstanceId(pi.getId()).count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessWithBoundary() throws Exception {
Date startTime = new Date();
// Test terminating process via boundary timer
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventWithBoundary");
assertEquals(3, taskService.createTaskQuery().processInstanceId(pi.getId()).count());
// Set clock time to '1 hour and 5 seconds' ahead to fire timer
processEngineConfiguration.getClock().setCurrentTime(new Date(startTime.getTime() + ((60 * 60 * 1000) + 5000)));
waitForJobExecutorToProcessAllJobs(5000L, 25L);
// timer has fired
assertEquals(0L, managementService.createJobQuery().count());
assertProcessEnded(pi.getId());
// Test terminating subprocess
pi = runtimeService.startProcessInstanceByKey("terminateEndEventWithBoundary");
assertEquals(3, taskService.createTaskQuery().processInstanceId(pi.getId()).count());
// a job for boundary event timer should exist
assertEquals(1L, managementService.createJobQuery().count());
// Complete sub process task that leads to a terminate end event
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTermInnerTask").singleResult();
taskService.complete(task.getId());
// 'preEndInnerTask' task in subprocess should have been terminated, only outerTask should exist
assertEquals(1, taskService.createTaskQuery().processInstanceId(pi.getId()).count());
// job for boundary event timer should have been removed
assertEquals(0L, managementService.createJobQuery().count());
// complete outerTask
task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("outerTask").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessWithBoundaryTerminateAll() throws Exception {
// Test terminating subprocess
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventWithBoundary");
assertEquals(3, taskService.createTaskQuery().processInstanceId(pi.getId()).count());
// Complete sub process task that leads to a terminate end event
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preTermInnerTask").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessConcurrent() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessConcurrentTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessConcurrentTerminateAll2() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).list();
assertEquals(2, tasks.size());
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskName("User Task").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessConcurrentMultiInstance() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(12, executionEntities);
List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).list();
assertEquals(4, tasks.size()); // 3 user tasks in MI +1 (preNormalEnd) = 4 (2 were killed because it went directly to the terminate end event)
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
long executionEntities2 = runtimeService.createExecutionQuery().count();
assertEquals(10, executionEntities2);
tasks = taskService.createTaskQuery().list();
for (Task t : tasks) {
taskService.complete(t.getId());
}
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessConcurrentMultiInstance2() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).taskName("User Task").list();
assertEquals(3, tasks.size());
for (Task t : tasks) {
taskService.complete(t.getId());
}
assertProcessEnded(pi.getId());
}
@Deployment
public void testTerminateInSubProcessConcurrentMultiInstanceTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
}
@Deployment(resources = {"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityConcurrentCallActivity.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateAfterUserTask.bpmn",
"org/activiti/engine/test/api/oneTaskProcess.bpmn20.xml"})
public void testTerminateInCallActivityConcurrentCallActivity() throws Exception {
// GIVEN - process instance starts and creates 2 subProcessInstances (with 2 user tasks - preTerminate and my task)
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventInCallActivityConcurrentCallActivity");
assertThat(runtimeService.createProcessInstanceQuery().superProcessInstanceId(pi.getId()).list().size(), is(2));
// WHEN - complete -> terminate end event
Task preTerminate = taskService.createTaskQuery().taskName("preTerminate").singleResult();
taskService.complete(preTerminate.getId());
//THEN - super process is not finished together
assertEquals(1, runtimeService.createProcessInstanceQuery().processInstanceId(pi.getId()).count());
}
@Deployment
public void testTerminateInSubProcessMultiInstance() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessSequentialConcurrentMultiInstance() throws Exception {
// Starting multi instance with 5 instances; terminating 2, finishing 3
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
long remainingExecutions = runtimeService.createExecutionQuery().count();
// outer execution still available
assertEquals(1, remainingExecutions);
// three finished
assertEquals(3, serviceTaskInvokedCount2);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
// last task remaining
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateInSubProcessSequentialConcurrentMultiInstanceTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources={
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivity.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessTerminate.bpmn"
})
public void testTerminateInCallActivity() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// should terminate the called process and continue the parent
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources={
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityMulitInstance.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessTerminate.bpmn"
})
public void testTerminateInCallActivityMultiInstance() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// should terminate the called process and continue the parent
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources = {
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityMulitInstance.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessTerminateTerminateAll.bpmn20.xml" })
public void testTerminateInCallActivityMultiInstanceTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources={
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityConcurrent.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessConcurrentTerminate.bpmn"
})
public void testTerminateInCallActivityConcurrent() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// should terminate the called process and continue the parent
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testMiCallActivityParallel() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("testMiCallActivity");
List<Task> aTasks = taskService.createTaskQuery().taskName("A").list();
assertEquals(5, aTasks.size());
List<Task> bTasks = taskService.createTaskQuery().taskName("B").list();
assertEquals(5, bTasks.size());
// Completing B should terminate one instance (it goes to a terminate end event)
int bTasksCompleted = 0;
for (Task bTask : bTasks) {
taskService.complete(bTask.getId());
bTasksCompleted++;
aTasks = taskService.createTaskQuery().taskName("A").list();
assertEquals(5-bTasksCompleted, aTasks.size());
}
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("After call activity", task.getName());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testMiCallActivitySequential() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("testMiCallActivity");
List<Task> aTasks = taskService.createTaskQuery().taskName("A").list();
assertEquals(1, aTasks.size());
List<Task> bTasks = taskService.createTaskQuery().taskName("B").list();
assertEquals(1, bTasks.size());
// Completing B should terminate one instance (it goes to a terminate end event)
for (int i=0; i<9; i++) {
Task bTask = taskService.createTaskQuery().taskName("B").singleResult();
taskService.complete(bTask.getId());
if (i != 8) {
aTasks = taskService.createTaskQuery().taskName("A").list();
assertEquals(1, aTasks.size());
bTasks = taskService.createTaskQuery().taskName("B").list();
assertEquals(1, bTasks.size());
}
}
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
assertEquals("After call activity", task.getName());
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment(resources={
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityConcurrent.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessConcurrentTerminateTerminateAll.bpmn20.xml"
})
public void testTerminateInCallActivityConcurrentTerminateAll() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources={
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityConcurrentMulitInstance.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessConcurrentTerminate.bpmn"
})
public void testTerminateInCallActivityConcurrentMulitInstance() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
// should terminate the called process and continue the parent
long executionEntities = runtimeService.createExecutionQuery().count();
assertEquals(1, executionEntities);
Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).taskDefinitionKey("preNormalEnd").singleResult();
taskService.complete(task.getId());
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment(resources = {
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.testTerminateInCallActivityConcurrentMulitInstance.bpmn",
"org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.subProcessConcurrentTerminateTerminateAll.bpmn20.xml" })
public void testTerminateInCallActivityConcurrentMulitInstanceTerminateALl() throws Exception {
ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateEndEventExample");
assertProcessEnded(pi.getId());
assertHistoricProcessInstanceDetails(pi);
}
@Deployment
public void testTerminateNestedSubprocesses() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedSubprocesses");
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).orderByTaskName().asc().list();
assertEquals("A", tasks.get(0).getName());
assertEquals("B", tasks.get(1).getName());
assertEquals("D", tasks.get(2).getName());
assertEquals("E", tasks.get(3).getName());
assertEquals("F", tasks.get(4).getName());
// Completing E should finish the lower subprocess and make 'H' active
taskService.complete(tasks.get(3).getId());
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("H").singleResult();
assertNotNull(task);
// Completing A should make C active
taskService.complete(tasks.get(0).getId());
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("C").singleResult();
assertNotNull(task);
// Completing C should make I active
taskService.complete(task.getId());
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("I").singleResult();
assertNotNull(task);
// Completing I and B should make G active
taskService.complete(task.getId());
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("G").singleResult();
assertNull(task);
taskService.complete(tasks.get(1).getId());
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("G").singleResult();
assertNotNull(task);
}
@Deployment
public void testTerminateNestedSubprocessesTerminateAll1() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedSubprocesses");
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("E").singleResult();
// Completing E leads to a terminate end event with termninate all set to true
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testTerminateNestedSubprocessesTerminateAll2() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedSubprocesses");
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("A").singleResult();
// Completing A and C leads to a terminate end event with termninate all set to true
taskService.complete(task.getId());
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("C").singleResult();
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testTerminateNestedMiSubprocesses() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedMiSubprocesses");
taskService.complete(taskService.createTaskQuery().taskName("A").singleResult().getId());
// Should have 7 tasks C active
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("C").list();
assertEquals(7, tasks.size());
// Completing these should lead to task I being active
for (Task task : tasks) {
taskService.complete(task.getId());
}
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("I").singleResult();
assertNotNull(task);
// Should have 3 instances of E active
tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("E").list();
assertEquals(3, tasks.size());
// Completing these should make H active
for (Task t : tasks) {
taskService.complete(t.getId());
}
task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("H").singleResult();
assertNotNull(task);
}
@Deployment
public void testTerminateNestedMiSubprocessesSequential() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedMiSubprocesses");
taskService.complete(taskService.createTaskQuery().taskName("A").singleResult().getId());
// Should have 7 tasks C active after each other
for (int i=0; i<7; i++) {
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("C").singleResult();
taskService.complete(task.getId());
}
// I should be active now
assertNotNull(taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("I").singleResult());
// Should have 3 instances of E active after each other
for (int i=0; i<3; i++) {
assertEquals(1, taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("D").count());
assertEquals(1, taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("F").count());
// Completing F should not finish the subprocess
taskService.complete(taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("F").singleResult().getId());
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("E").singleResult();
taskService.complete(task.getId());
}
assertNotNull(taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("H").singleResult());
}
@Deployment
public void testTerminateNestedMiSubprocessesTerminateAll1() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedMiSubprocesses");
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("E").list().get(0);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testTerminateNestedMiSubprocessesTerminateAll2() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedMiSubprocesses");
taskService.complete(taskService.createTaskQuery().taskName("A").singleResult().getId());
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("C").list().get(0);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testTerminateNestedMiSubprocessesTerminateAll3() { // Same as 1, but sequential Multi-Instance
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedMiSubprocesses");
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("E").list().get(0);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testTerminateNestedMiSubprocessesTerminateAll4() { // Same as 2, but sequential Multi-Instance
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestTerminateNestedMiSubprocesses");
taskService.complete(taskService.createTaskQuery().taskName("A").singleResult().getId());
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskName("C").list().get(0);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
@Deployment
public void testNestedCallActivities() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestNestedCallActivities");
// Verify the tasks
List<Task> tasks = assertTaskNames(processInstance,
Arrays.asList("B", "B", "B", "B", "Before A", "Before A", "Before A", "Before A", "Before B", "Before C"));
// Completing 'before c'
taskService.complete(tasks.get(9).getId());
tasks = assertTaskNames(processInstance,
Arrays.asList("After C", "B", "B", "B", "B", "Before A", "Before A", "Before A", "Before A", "Before B"));
// Completing 'before A' of one instance
Task task = taskService.createTaskQuery().taskName("task_subprocess_1").singleResult();
assertNull(task);
taskService.complete(tasks.get(5).getId());
// Multi instance call activity is sequential, so expecting 5 more times the same task
for (int i=0; i<6; i++) {
task = taskService.createTaskQuery().taskName("subprocess1_task").singleResult();
assertNotNull("Task is null for index " + i, task);
taskService.complete(task.getId());
}
tasks = assertTaskNames(processInstance,
Arrays.asList("After A", "After C", "B", "B", "B", "B", "Before A", "Before A", "Before A", "Before B"));
}
@Deployment
public void testNestedCallActivitiesTerminateAll() {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("TestNestedCallActivities");
// Verify the tasks
List<Task> tasks = assertTaskNames(processInstance,
Arrays.asList("B", "B", "B", "B", "Before A", "Before A", "Before A", "Before A", "Before B", "Before C"));
// Completing 'Before B' should lead to process instance termination
taskService.complete(tasks.get(8).getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
// Completing 'Before C' too
processInstance = runtimeService.startProcessInstanceByKey("TestNestedCallActivities");
tasks = assertTaskNames(processInstance,
Arrays.asList("B", "B", "B", "B", "Before A", "Before A", "Before A", "Before A", "Before B", "Before C"));
taskService.complete(tasks.get(9).getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
// Now the tricky one. 'Before A' leads to 'callActivity A', which calls subprocess02 which terminates
processInstance = runtimeService.startProcessInstanceByKey("TestNestedCallActivities");
tasks = assertTaskNames(processInstance,
Arrays.asList("B", "B", "B", "B", "Before A", "Before A", "Before A", "Before A", "Before B", "Before C"));
taskService.complete(tasks.get(5).getId());
Task task = taskService.createTaskQuery().taskName("subprocess1_task").singleResult();
assertNotNull(task);
taskService.complete(task.getId());
assertProcessEnded(processInstance.getId());
assertHistoricProcessInstanceDetails(processInstance);
}
private List<Task> assertTaskNames(ProcessInstance processInstance, List<String> taskNames) {
List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).orderByTaskName().asc().list();
for (int i=0; i<taskNames.size(); i++) {
assertEquals("Task name at index " + i + " does not match", taskNames.get(i), tasks.get(i).getName());
}
return tasks;
}
public void testParseTerminateEndEventDefinitionWithExtensions() {
org.activiti.engine.repository.Deployment deployment = repositoryService.createDeployment().addClasspathResource("org/activiti/engine/test/bpmn/event/end/TerminateEndEventTest.parseExtensionElements.bpmn20.xml").deploy();
ProcessDefinition processDefinitionQuery = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
ProcessDefinitionEntity processDefinition = this.processEngineConfiguration.getProcessDefinitionCache().get(processDefinitionQuery.getId());
assertThat(processDefinition.getActivities().size(), is(2));
ActivityImpl endEvent = processDefinition.getActivities().get(1);
assertThat(endEvent.getId(), is("terminateEnd"));
assertThat(endEvent.getActivityBehavior(), instanceOf(TerminateEndEventActivityBehavior.class));
TerminateEndEventActivityBehavior terminateEndEventBehavior = (TerminateEndEventActivityBehavior) endEvent.getActivityBehavior();
Map<String, List<ExtensionElement>> extensionElements = terminateEndEventBehavior.getEndEvent().getExtensionElements();
assertThat(extensionElements.size(), is(1));
List<ExtensionElement> strangeProperties = extensionElements.get("strangeProperty");
assertThat(strangeProperties.size(), is(1));
ExtensionElement strangeProperty = strangeProperties.get(0);
assertThat(strangeProperty.getNamespace(), is("http://activiti.org/bpmn"));
assertThat(strangeProperty.getElementText(), is("value"));
assertThat(strangeProperty.getAttributes().size(), is(1));
ExtensionAttribute id = strangeProperty.getAttributes().get("id").get(0);
assertThat(id.getName(), is("id"));
assertThat(id.getValue(), is("strangeId"));
repositoryService.deleteDeployment(deployment.getId());
}
// Unit test for ACT-4101 : NPE when there are multiple routes to terminateEndEvent, and both are reached
@Deployment
public void testThreeExecutionsArrivingInTerminateEndEvent() {
Map<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("passed_QC", false);
variableMap.put("has_bad_pixel_pattern", true);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("skybox_image_pull_request", variableMap);
String processInstanceId = processInstance.getId();
assertNotNull(processInstance);
while(processInstance != null) {
List<Execution> executionList = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).list();
String activityId = "";
for (Execution execution : executionList) {
activityId = execution.getActivityId();
if (activityId == null
|| activityId.equalsIgnoreCase("quality_control_passed_gateway")
|| activityId.equalsIgnoreCase("parallelgateway1")
|| activityId.equalsIgnoreCase("catch_bad_pixel_signal")
|| activityId.equalsIgnoreCase("throw_bad_pixel_signal")
|| activityId.equalsIgnoreCase("has_bad_pixel_pattern")
|| activityId.equalsIgnoreCase("")) {
continue;
}
System.out.println("Current Activity:" + activityId);
runtimeService.signal(execution.getId());
}
processInstance =
runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
}
assertProcessEnded(processInstanceId);
assertHistoricProcessInstanceDetails(processInstanceId);
}
protected void assertHistoricProcessInstanceDetails(String processInstanceId) {
if (processEngineConfiguration.getHistoryLevel().isAtLeast(HistoryLevel.ACTIVITY)) {
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
assertHistoricProcessInstance(historicProcessInstance);
}
}
protected void assertHistoricProcessInstanceDetails(ProcessInstance pi) {
if (processEngineConfiguration.getHistoryLevel().isAtLeast(HistoryLevel.ACTIVITY)) {
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(pi.getId()).singleResult();
assertHistoricProcessInstance(historicProcessInstance);
}
}
protected void assertHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) {
assertNotNull(historicProcessInstance.getEndTime());
assertNotNull(historicProcessInstance.getDurationInMillis());
assertNotNull(historicProcessInstance.getEndActivityId());
}
}