diff --git a/engine/src/main/java/org/camunda/bpm/engine/impl/cmd/AbstractInstantiationCmd.java b/engine/src/main/java/org/camunda/bpm/engine/impl/cmd/AbstractInstantiationCmd.java index e74aaf29ef1..e2791a70f44 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/impl/cmd/AbstractInstantiationCmd.java +++ b/engine/src/main/java/org/camunda/bpm/engine/impl/cmd/AbstractInstantiationCmd.java @@ -86,6 +86,14 @@ public VariableMap getVariablesLocal() { return variablesLocal; } + public String getAncestorActivityInstanceId() { + return ancestorActivityInstanceId; + } + + public void setAncestorActivityInstanceId(String ancestorActivityInstanceId) { + this.ancestorActivityInstanceId = ancestorActivityInstanceId; + } + public Void execute(final CommandContext commandContext) { ExecutionEntity processInstance = commandContext.getExecutionManager().findExecutionById(processInstanceId); @@ -326,7 +334,6 @@ else if (PvmActivity.class.isAssignableFrom(targetElement.getClass())) { } } - protected void instantiateConcurrent(ExecutionEntity ancestorScopeExecution, List parentFlowScopes, CoreModelElement targetElement) { if (PvmTransition.class.isAssignableFrom(targetElement.getClass())) { ancestorScopeExecution.executeActivitiesConcurrent(parentFlowScopes, null, (PvmTransition) targetElement, variables, diff --git a/engine/src/main/java/org/camunda/bpm/engine/impl/json/ModificationCmdJsonConverter.java b/engine/src/main/java/org/camunda/bpm/engine/impl/json/ModificationCmdJsonConverter.java index 0710ebb21ea..35198890085 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/impl/json/ModificationCmdJsonConverter.java +++ b/engine/src/main/java/org/camunda/bpm/engine/impl/json/ModificationCmdJsonConverter.java @@ -16,6 +16,7 @@ */ package org.camunda.bpm.engine.impl.json; +import com.google.gson.JsonObject; import org.camunda.bpm.engine.impl.cmd.AbstractProcessInstanceModificationCommand; import org.camunda.bpm.engine.impl.cmd.ActivityAfterInstantiationCmd; import org.camunda.bpm.engine.impl.cmd.ActivityBeforeInstantiationCmd; @@ -24,7 +25,6 @@ import org.camunda.bpm.engine.impl.cmd.TransitionInstanceCancellationCmd; import org.camunda.bpm.engine.impl.cmd.TransitionInstantiationCmd; import org.camunda.bpm.engine.impl.util.JsonUtil; -import com.google.gson.JsonObject; public class ModificationCmdJsonConverter extends JsonObjectConverter { @@ -38,6 +38,7 @@ public class ModificationCmdJsonConverter extends JsonObjectConverter vars = new HashMap<>(); + vars.put("ids", new ArrayList<>(Arrays.asList("1"))); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("loopProcess", vars); + ActivityInstance tree = runtimeService.getActivityInstance(processInstance.getId()); + String ancestorActivityId = getChildInstanceForActivity(tree, "loop").getId(); + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) + .cancelActivityInstance(getChildInstanceForActivity(tree, "task").getId()) + .startBeforeActivity("task", ancestorActivityId) + .executeAsync(); + assertNotNull(modificationBatch); + + try { + // when + executeSeedAndBatchJobs(modificationBatch); + fail( + "It should not be possible to start before the 'task' activity because the 'task' activity has already been cancelled."); + } catch (ProcessEngineException e) { + // then + testRule.assertTextPresentIgnoreCase( + "Cannot perform instruction: Start before activity 'task' with ancestor activity instance '" + + ancestorActivityId + "'; Ancestor activity instance '" + ancestorActivityId + + "' does not exist: ancestorInstance is null", e.getMessage()); + } + } @Deployment(resources = EXCLUSIVE_GATEWAY_PROCESS) @Test @@ -246,13 +299,16 @@ public void testStartBeforeNonExistingActivity() { try { // when - Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()).startBeforeActivity("someNonExistingActivity").executeAsync(); + Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()) + .startBeforeActivity("someNonExistingActivity") + .executeAsync(); assertNotNull(modificationBatch); executeSeedAndBatchJobs(modificationBatch); fail("should not succeed"); } catch (NotValidException e) { // then - testRule.assertTextPresentIgnoreCase("element 'someNonExistingActivity' does not exist in process ", e.getMessage()); + testRule.assertTextPresentIgnoreCase("element 'someNonExistingActivity' does not exist in process ", + e.getMessage()); } } @@ -277,7 +333,8 @@ public void testEndProcessInstanceIntermediately() { ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1").done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); @@ -296,8 +353,7 @@ public void testStartTransition() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("exclusiveGateway"); String processInstanceId = processInstance.getId(); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startTransition("flow4") .executeAsync(); assertNotNull(modificationBatch); @@ -307,12 +363,22 @@ public void testStartTransition() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1").activity("task2").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1") + .activity("task2") + .done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); - assertThat(executionTree) - .matches(describeExecutionTree(null).scope().child("task1").concurrent().noScope().up().child("task2").concurrent().noScope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child("task1") + .concurrent() + .noScope() + .up() + .child("task2") + .concurrent() + .noScope() + .done()); assertEquals(2, taskService.createTaskQuery().count()); @@ -329,8 +395,7 @@ public void testStartTransitionWithAncestorInstanceId() { ActivityInstance tree = runtimeService.getActivityInstance(processInstanceId); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startTransition("flow4", tree.getId()) .executeAsync(); assertNotNull(modificationBatch); @@ -340,12 +405,22 @@ public void testStartTransitionWithAncestorInstanceId() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1").activity("task2").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1") + .activity("task2") + .done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); - assertThat(executionTree) - .matches(describeExecutionTree(null).scope().child("task1").concurrent().noScope().up().child("task2").concurrent().noScope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child("task1") + .concurrent() + .noScope() + .up() + .child("task2") + .concurrent() + .noScope() + .done()); assertEquals(2, taskService.createTaskQuery().count()); @@ -361,7 +436,9 @@ public void testStartTransitionInvalidTransitionId() { String processInstanceId = processInstance.getId(); try { - Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstanceId).startTransition("invalidFlowId").executeAsync(); + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstanceId) + .startTransition("invalidFlowId") + .executeAsync(); assertNotNull(modificationBatch); executeSeedAndBatchJobs(modificationBatch); @@ -369,8 +446,9 @@ public void testStartTransitionInvalidTransitionId() { } catch (ProcessEngineException e) { // happy path - testRule.assertTextPresent("Cannot perform instruction: " + "Start transition 'invalidFlowId'; " + "Element 'invalidFlowId' does not exist in process '" - + processInstance.getProcessDefinitionId() + "'", e.getMessage()); + testRule.assertTextPresent("Cannot perform instruction: " + "Start transition 'invalidFlowId'; " + + "Element 'invalidFlowId' does not exist in process '" + processInstance.getProcessDefinitionId() + "'", + e.getMessage()); } } @@ -380,8 +458,7 @@ public void testStartAfter() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("exclusiveGateway"); String processInstanceId = processInstance.getId(); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startAfterActivity("theStart") .executeAsync(); assertNotNull(modificationBatch); @@ -391,12 +468,22 @@ public void testStartAfter() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1").activity("task1").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1") + .activity("task1") + .done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); - assertThat(executionTree) - .matches(describeExecutionTree(null).scope().child("task1").concurrent().noScope().up().child("task1").concurrent().noScope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child("task1") + .concurrent() + .noScope() + .up() + .child("task1") + .concurrent() + .noScope() + .done()); assertEquals(2, taskService.createTaskQuery().count()); @@ -413,8 +500,7 @@ public void testStartAfterWithAncestorInstanceId() { ActivityInstance tree = runtimeService.getActivityInstance(processInstanceId); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startAfterActivity("theStart", tree.getId()) .executeAsync(); assertNotNull(modificationBatch); @@ -424,12 +510,22 @@ public void testStartAfterWithAncestorInstanceId() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1").activity("task1").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task1") + .activity("task1") + .done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); - assertThat(executionTree) - .matches(describeExecutionTree(null).scope().child("task1").concurrent().noScope().up().child("task1").concurrent().noScope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child("task1") + .concurrent() + .noScope() + .up() + .child("task1") + .concurrent() + .noScope() + .done()); assertEquals(2, taskService.createTaskQuery().count()); @@ -438,6 +534,34 @@ public void testStartAfterWithAncestorInstanceId() { testRule.assertProcessEnded(processInstanceId); } + @Deployment(resources = LOOP_PROCESS) + @Test + public void testStartAfterWithAncestorInstanceIdWithAncestorCancelled() { + // given + Map vars = new HashMap<>(); + vars.put("ids", new ArrayList<>(Arrays.asList("1"))); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("loopProcess", vars); + ActivityInstance tree = runtimeService.getActivityInstance(processInstance.getId()); + String ancestorActivityId = getChildInstanceForActivity(tree, "loop").getId(); + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) + .cancelActivityInstance(getChildInstanceForActivity(tree, "task").getId()) + .startAfterActivity("task", ancestorActivityId) + .executeAsync(); + assertNotNull(modificationBatch); + + try { + // when + executeSeedAndBatchJobs(modificationBatch); + fail( + "It should not be possible to start after the 'task' activity because the 'task' activity has already been cancelled."); + } catch (ProcessEngineException e) { + // then + testRule.assertTextPresentIgnoreCase( + "Cannot perform instruction: Start after activity 'task' with ancestor activity instance '" + + ancestorActivityId + "'; Ancestor activity instance '" + ancestorActivityId + + "' does not exist: ancestorInstance is null", e.getMessage()); + } + } @Deployment(resources = EXCLUSIVE_GATEWAY_PROCESS) @Test @@ -446,8 +570,7 @@ public void testStartAfterActivityAmbiguousTransitions() { String processInstanceId = processInstance.getId(); try { - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstanceId) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstanceId) .startAfterActivity("fork") .executeAsync(); assertNotNull(modificationBatch); @@ -466,8 +589,7 @@ public void testStartAfterActivityNoOutgoingTransitions() { String processInstanceId = processInstance.getId(); try { - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstanceId) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstanceId) .startAfterActivity("theEnd") .executeAsync(); assertNotNull(modificationBatch); @@ -488,8 +610,7 @@ public void testStartAfterNonExistingActivity() { try { // when - Batch modificationBatch = runtimeService - .createProcessInstanceModification(instance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()) .startAfterActivity("someNonExistingActivity") .executeAsync(); assertNotNull(modificationBatch); @@ -497,8 +618,9 @@ public void testStartAfterNonExistingActivity() { fail("should not succeed"); } catch (NotValidException e) { // then - testRule.assertTextPresentIgnoreCase("Cannot perform instruction: " + "Start after activity 'someNonExistingActivity'; " - + "Activity 'someNonExistingActivity' does not exist: activity is null", e.getMessage()); + testRule.assertTextPresentIgnoreCase( + "Cannot perform instruction: " + "Start after activity 'someNonExistingActivity'; " + + "Activity 'someNonExistingActivity' does not exist: activity is null", e.getMessage()); } } @@ -508,8 +630,7 @@ public void testScopeTaskStartBefore() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); String processInstanceId = processInstance.getId(); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startBeforeActivity("theTask") .executeAsync(); assertNotNull(modificationBatch); @@ -519,12 +640,27 @@ public void testScopeTaskStartBefore() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("theTask").activity("theTask").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("theTask") + .activity("theTask") + .done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); - assertThat(executionTree).matches(describeExecutionTree(null).scope().child(null).concurrent().noScope().child("theTask").scope().up().up().child(null) - .concurrent().noScope().child("theTask").scope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child(null) + .concurrent() + .noScope() + .child("theTask") + .scope() + .up() + .up() + .child(null) + .concurrent() + .noScope() + .child("theTask") + .scope() + .done()); assertEquals(2, taskService.createTaskQuery().count()); completeTasksInOrder("theTask", "theTask"); @@ -539,8 +675,7 @@ public void testScopeTaskStartAfter() { // when starting after the task, essentially nothing changes in the process // instance - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startAfterActivity("theTask") .executeAsync(); assertNotNull(modificationBatch); @@ -550,14 +685,17 @@ public void testScopeTaskStartAfter() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("theTask").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("theTask").done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); assertThat(executionTree).matches(describeExecutionTree(null).scope().child("theTask").scope().done()); // when starting after the start event, regular concurrency happens - Batch modificationBatch2 = runtimeService.createProcessInstanceModification(processInstance.getId()).startAfterActivity("theStart").executeAsync(); + Batch modificationBatch2 = runtimeService.createProcessInstanceModification(processInstance.getId()) + .startAfterActivity("theStart") + .executeAsync(); assertNotNull(modificationBatch2); executeSeedAndBatchJobs(modificationBatch2); @@ -565,12 +703,27 @@ public void testScopeTaskStartAfter() { assertNotNull(updatedTree); assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("theTask").activity("theTask").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("theTask") + .activity("theTask") + .done()); executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); - assertThat(executionTree).matches(describeExecutionTree(null).scope().child(null).concurrent().noScope().child("theTask").scope().up().up().child(null) - .concurrent().noScope().child("theTask").scope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child(null) + .concurrent() + .noScope() + .child("theTask") + .scope() + .up() + .up() + .child(null) + .concurrent() + .noScope() + .child("theTask") + .scope() + .done()); completeTasksInOrder("theTask", "theTask"); testRule.assertProcessEnded(processInstanceId); @@ -580,15 +733,14 @@ public void testScopeTaskStartAfter() { @Test public void testSkipTaskListenerInvocation() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("taskListenerProcess", "brum", - Collections. singletonMap("listener", new RecorderTaskListener())); + Collections.singletonMap("listener", new RecorderTaskListener())); String processInstanceId = processInstance.getId(); RecorderTaskListener.clear(); // when I start an activity with "skip listeners" setting - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstanceId) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstanceId) .startBeforeActivity("task") .executeAsync(true, false); assertNotNull(modificationBatch); @@ -600,8 +752,7 @@ public void testSkipTaskListenerInvocation() { // when I cancel an activity with "skip listeners" setting ActivityInstance activityInstanceTree = runtimeService.getActivityInstance(processInstanceId); - Batch batch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch batch = runtimeService.createProcessInstanceModification(processInstance.getId()) .cancelActivityInstance(getChildInstanceForActivity(activityInstanceTree, "task").getId()) .executeAsync(true, false); assertNotNull(batch); @@ -617,8 +768,7 @@ public void testSkipIoMappings() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ioMappingProcess"); // when I start task2 - Batch modificationBatch = runtimeService - .createProcessInstanceModification(processInstance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(processInstance.getId()) .startBeforeActivity("task2") .executeAsync(false, true); assertNotNull(modificationBatch); @@ -631,7 +781,9 @@ public void testSkipIoMappings() { assertNull(runtimeService.getVariable(task2Execution.getId(), "inputMappingExecuted")); // when I cancel task2 - Batch modificationBatch2 = runtimeService.createProcessInstanceModification(processInstance.getId()).cancelAllForActivity("task2").executeAsync(false, true); + Batch modificationBatch2 = runtimeService.createProcessInstanceModification(processInstance.getId()) + .cancelAllForActivity("task2") + .executeAsync(false, true); assertNotNull(modificationBatch2); executeSeedAndBatchJobs(modificationBatch2); @@ -647,8 +799,7 @@ public void testStartTransitionListenerInvocation() { ProcessInstance instance = runtimeService.startProcessInstanceByKey("transitionListenerProcess", Variables.createVariables().putValue("listener", new RecorderExecutionListener())); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(instance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()) .startTransition("flow2") .executeAsync(); assertNotNull(modificationBatch); @@ -667,12 +818,20 @@ public void testStartTransitionListenerInvocation() { assertNotNull(updatedTree); assertEquals(instance.getId(), updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(instance.getProcessDefinitionId()).activity("task1").activity("task2").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(instance.getProcessDefinitionId()).activity("task1").activity("task2").done()); ExecutionTree executionTree = ExecutionTree.forExecution(instance.getId(), processEngine); - assertThat(executionTree) - .matches(describeExecutionTree(null).scope().child("task1").concurrent().noScope().up().child("task2").concurrent().noScope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child("task1") + .concurrent() + .noScope() + .up() + .child("task2") + .concurrent() + .noScope() + .done()); completeTasksInOrder("task1", "task2", "task2"); testRule.assertProcessEnded(instance.getId()); @@ -686,8 +845,7 @@ public void testStartAfterActivityListenerInvocation() { ProcessInstance instance = runtimeService.startProcessInstanceByKey("transitionListenerProcess", Variables.createVariables().putValue("listener", new RecorderExecutionListener())); - Batch modificationBatch = runtimeService - .createProcessInstanceModification(instance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()) .startTransition("flow2") .executeAsync(); assertNotNull(modificationBatch); @@ -706,12 +864,20 @@ public void testStartAfterActivityListenerInvocation() { assertNotNull(updatedTree); assertEquals(instance.getId(), updatedTree.getProcessInstanceId()); - assertThat(updatedTree).hasStructure(describeActivityInstanceTree(instance.getProcessDefinitionId()).activity("task1").activity("task2").done()); + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree(instance.getProcessDefinitionId()).activity("task1").activity("task2").done()); ExecutionTree executionTree = ExecutionTree.forExecution(instance.getId(), processEngine); - assertThat(executionTree) - .matches(describeExecutionTree(null).scope().child("task1").concurrent().noScope().up().child("task2").concurrent().noScope().done()); + assertThat(executionTree).matches(describeExecutionTree(null).scope() + .child("task1") + .concurrent() + .noScope() + .up() + .child("task2") + .concurrent() + .noScope() + .done()); completeTasksInOrder("task1", "task2", "task2"); testRule.assertProcessEnded(instance.getId()); @@ -736,7 +902,8 @@ public void testCancellationAndStartBefore() { assertNotNull(activityInstanceTree); assertEquals(processInstanceId, activityInstanceTree.getProcessInstanceId()); - assertThat(activityInstanceTree).hasStructure(describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task2").done()); + assertThat(activityInstanceTree).hasStructure( + describeActivityInstanceTree(processInstance.getProcessDefinitionId()).activity("task2").done()); ExecutionTree executionTree = ExecutionTree.forExecution(processInstanceId, processEngine); @@ -754,8 +921,7 @@ public void testCancelNonExistingActivityInstance() { // when - then throw exception try { - Batch modificationBatch = runtimeService - .createProcessInstanceModification(instance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()) .cancelActivityInstance("nonExistingActivityInstance") .executeAsync(); assertNotNull(modificationBatch); @@ -776,16 +942,16 @@ public void testCancelNonExistingTranisitionInstance() { // when - then throw exception try { - Batch modificationBatch = runtimeService - .createProcessInstanceModification(instance.getId()) + Batch modificationBatch = runtimeService.createProcessInstanceModification(instance.getId()) .cancelTransitionInstance("nonExistingActivityInstance") .executeAsync(); assertNotNull(modificationBatch); executeSeedAndBatchJobs(modificationBatch); fail("should not succeed"); } catch (NotValidException e) { - testRule.assertTextPresent("Cannot perform instruction: Cancel transition instance 'nonExistingActivityInstance'; " - + "Transition instance 'nonExistingActivityInstance' does not exist", e.getMessage()); + testRule.assertTextPresent( + "Cannot perform instruction: Cancel transition instance 'nonExistingActivityInstance'; " + + "Transition instance 'nonExistingActivityInstance' does not exist", e.getMessage()); } } @@ -795,7 +961,9 @@ public void testCancelNonExistingTranisitionInstance() { public void testCancelCallActivityInstance() { // given ProcessInstance parentprocess = runtimeService.startProcessInstanceByKey("parentprocess"); - ProcessInstance subProcess = runtimeService.createProcessInstanceQuery().processDefinitionKey("subprocess").singleResult(); + ProcessInstance subProcess = runtimeService.createProcessInstanceQuery() + .processDefinitionKey("subprocess") + .singleResult(); ActivityInstance subProcessActivityInst = runtimeService.getActivityInstance(subProcess.getId()); @@ -814,8 +982,7 @@ public void testCancelCallActivityInstance() { @Test public void testModifyNullProcessInstance() { try { - Batch modificationBatch = runtimeService - .createProcessInstanceModification(null) + Batch modificationBatch = runtimeService.createProcessInstanceModification(null) .startBeforeActivity("someActivity") .executeAsync(); assertNotNull(modificationBatch); @@ -830,8 +997,7 @@ public void testModifyNullProcessInstance() { @Test public void testSetInvocationsPerBatchType() { // given - processEngineConfiguration.getInvocationsPerBatchJobByBatchType() - .put(Batch.TYPE_PROCESS_INSTANCE_MODIFICATION, 42); + processEngineConfiguration.getInvocationsPerBatchJobByBatchType().put(Batch.TYPE_PROCESS_INSTANCE_MODIFICATION, 42); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("parallelGateway"); @@ -854,7 +1020,6 @@ protected void executeSeedAndBatchJobs(Batch batch) { // seed job managementService.executeJob(job.getId()); - for (Job pending : managementService.createJobQuery().jobDefinitionId(batch.getBatchJobDefinitionId()).list()) { managementService.executeJob(pending.getId()); } diff --git a/engine/src/test/resources/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.loop.bpmn b/engine/src/test/resources/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.loop.bpmn new file mode 100644 index 00000000000..28cd45cfbd2 --- /dev/null +++ b/engine/src/test/resources/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.loop.bpmn @@ -0,0 +1,70 @@ + + + + + Flow_10b3t9t + + + Flow_10b3t9t + Flow_13ek3ki + + + Flow_1qch4x2 + Flow_0tvbudp + + + Flow_1qch4x2 + + + Flow_0tvbudp + + + + + + + Flow_13ek3ki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +