diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java index 833b28d9b1b..61d03b26c77 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java @@ -822,7 +822,10 @@ protected List createEmbeddedSubProcessAndExecutions(Collection // Build the subProcess hierarchy for (SubProcess subProcess : subProcessesToCreate.values()) { - if (!processInstanceChangeState.getCreatedEmbeddedSubProcesses().containsKey(subProcess.getId())) { + if (subProcess instanceof EventSubProcess) { + ExecutionEntity embeddedSubProcess = createEmbeddedSubProcessHierarchy(subProcess, defaultContinueParentExecution, subProcessesToCreate, movingExecutionIds, processInstanceChangeState, commandContext); + moveExecutionEntityContainer.addCreatedEventSubProcess(subProcess.getId(), embeddedSubProcess); + } else if (!processInstanceChangeState.getCreatedEmbeddedSubProcesses().containsKey(subProcess.getId())) { ExecutionEntity embeddedSubProcess = createEmbeddedSubProcessHierarchy(subProcess, defaultContinueParentExecution, subProcessesToCreate, movingExecutionIds, processInstanceChangeState, commandContext); processInstanceChangeState.addCreatedEmbeddedSubProcess(subProcess.getId(), embeddedSubProcess); } @@ -833,7 +836,9 @@ protected List createEmbeddedSubProcessAndExecutions(Collection for (FlowElementMoveEntry flowElementMoveEntry : moveToFlowElements) { FlowElement newFlowElement = flowElementMoveEntry.getNewFlowElement(); ExecutionEntity parentExecution; - if (newFlowElement.getSubProcess() != null && processInstanceChangeState.getCreatedEmbeddedSubProcesses().containsKey(newFlowElement.getSubProcess().getId())) { + if (newFlowElement.getSubProcess() != null && moveExecutionEntityContainer.getCreatedEventSubProcess(newFlowElement.getSubProcess().getId()) != null) { + parentExecution = moveExecutionEntityContainer.getCreatedEventSubProcess(newFlowElement.getSubProcess().getId()); + } else if (newFlowElement.getSubProcess() != null && processInstanceChangeState.getCreatedEmbeddedSubProcesses().containsKey(newFlowElement.getSubProcess().getId())) { parentExecution = processInstanceChangeState.getCreatedEmbeddedSubProcesses().get(newFlowElement.getSubProcess().getId()); } else if ((newFlowElement instanceof Task || newFlowElement instanceof CallActivity) && isFlowElementMultiInstance(newFlowElement) && !movingExecutions.get(0).isMultiInstanceRoot() && diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/MoveExecutionEntityContainer.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/MoveExecutionEntityContainer.java index 6abb2b08869..66e0eb97aaa 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/MoveExecutionEntityContainer.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/MoveExecutionEntityContainer.java @@ -46,6 +46,7 @@ public class MoveExecutionEntityContainer { protected Map currentActivityToNewElementMap = new LinkedHashMap<>(); protected Map> flowElementLocalVariableMap = new HashMap<>(); protected List newExecutionIds = new ArrayList<>(); + protected Map createdEventSubProcesses = new HashMap<>(); public MoveExecutionEntityContainer(List executions, List moveToActivityIds) { this.executions = executions; @@ -216,6 +217,14 @@ public void addNewExecutionId(String executionId) { this.newExecutionIds.add(executionId); } + public ExecutionEntity getCreatedEventSubProcess(String processDefinitionId) { + return createdEventSubProcesses.get(processDefinitionId); + } + + public void addCreatedEventSubProcess(String processDefinitionId, ExecutionEntity executionEntity) { + createdEventSubProcesses.put(processDefinitionId, executionEntity); + } + public Map> getFlowElementLocalVariableMap() { return flowElementLocalVariableMap; } diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventRegistryEventSubprocessTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventRegistryEventSubprocessTest.java index 1a4a67310d4..4ffcdb27974 100644 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventRegistryEventSubprocessTest.java +++ b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventRegistryEventSubprocessTest.java @@ -12,6 +12,10 @@ */ package org.flowable.engine.test.api.runtime.migration; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + import org.assertj.core.groups.Tuple; import org.flowable.engine.migration.ProcessInstanceMigrationBuilder; import org.flowable.engine.migration.ProcessInstanceMigrationValidationResult; @@ -23,10 +27,6 @@ import org.flowable.task.api.Task; import org.junit.jupiter.api.Test; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - /** * @author Bas Claessen */ @@ -167,6 +167,86 @@ public void testMigrateNonInterruptingEventRegistryEventSubProcessWithStartedSub assertProcessEnded(processInstance.getId()); } + @Test + public void testMigrateNonInterruptingEventRegistryEventSubProcessWithTwoStartedSubProcess() { + //Deploy first version of the process + ProcessDefinition version1ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-eventregistry-event-subprocess.bpmn20.xml"); + + //Start an instance of the first version of the process for migration + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(version1ProcessDef.getKey()); + + //Deploy second version of the same process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-eventregistry-event-subprocess.bpmn20.xml"); + assertThat(version1ProcessDef.getId()).isNotEqualTo(version2ProcessDef.getId()); + + //Trigger event to create first sub process + inboundEventChannelAdapter.triggerTestEvent(); + //Trigger event to create second sub process + inboundEventChannelAdapter.triggerTestEvent(); + + //Confirm the state to migrate + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version1ProcessDef.getId()); + List tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()) + ); + List eventSubscriptions = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).list(); + assertThat(eventSubscriptions) + .extracting(EventSubscription::getEventType, EventSubscription::getActivityId, EventSubscription::getProcessDefinitionId) + .containsExactlyInAnyOrder(Tuple.tuple("myEvent", "eventSubProcessStart", version1ProcessDef.getId())); + + //Migrate to the other processDefinition + ProcessInstanceMigrationBuilder processInstanceMigrationBuilder = processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()); + + ProcessInstanceMigrationValidationResult processInstanceMigrationValidationResult = processInstanceMigrationBuilder + .validateMigration(processInstance.getId()); + assertThat(processInstanceMigrationValidationResult.isMigrationValid()).isTrue(); + + processInstanceMigrationBuilder.migrate(processInstance.getId()); + + //Confirm + executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version2ProcessDef.getId()); + tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()) + ); + + eventSubscriptions = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).list(); + assertThat(eventSubscriptions) + .extracting(EventSubscription::getEventType, EventSubscription::getActivityId, EventSubscription::getProcessDefinitionId) + .containsExactlyInAnyOrder(Tuple.tuple("myEvent", "eventSubProcessStart", version2ProcessDef.getId())); + + completeProcessInstanceTasks(processInstance.getId()); + assertProcessEnded(processInstance.getId()); + } + private EventSubscriptionQueryImpl createEventSubscriptionQuery() { return new EventSubscriptionQueryImpl(processEngineConfiguration.getCommandExecutor(), processEngineConfiguration.getEventSubscriptionServiceConfiguration()); } diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventSubProcessTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventSubProcessTest.java index b8610ab0689..e9eb62e6800 100644 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventSubProcessTest.java +++ b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationEventSubProcessTest.java @@ -412,6 +412,88 @@ public void testMigrateNonInterruptingSignalEventSubProcessWithStartedSubProcess assertProcessEnded(processInstance.getId()); } + @Test + public void testMigrateNonInterruptingSignalEventSubProcessWithTwoStartedSubProcess() { + //Deploy first version of the process + ProcessDefinition version1ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-signal-event-subprocess.bpmn20.xml"); + + //Start an instance of the first version of the process for migration + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(version1ProcessDef.getKey()); + + //Deploy second version of the same process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-signal-event-subprocess.bpmn20.xml"); + assertThat(version1ProcessDef.getId()).isNotEqualTo(version2ProcessDef.getId()); + + //Fire the signal to start the first sub process + runtimeService.signalEventReceived("eventSignal"); + //Fire the signal to start the second sub process + runtimeService.signalEventReceived("eventSignal"); + + //Confirm the state to migrate + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version1ProcessDef.getId()); + List tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()) + ); + List eventSubscriptions = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).list(); + assertThat(eventSubscriptions) + .extracting(EventSubscription::getEventName, EventSubscription::getActivityId, EventSubscription::getProcessDefinitionId) + .containsExactlyInAnyOrder(Tuple.tuple("eventSignal", "eventSubProcessStart", version1ProcessDef.getId())); + + changeStateEventListener.clear(); + + //Migrate to the other processDefinition + ProcessInstanceMigrationBuilder processInstanceMigrationBuilder = processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()); + + ProcessInstanceMigrationValidationResult processInstanceMigrationValidationResult = processInstanceMigrationBuilder + .validateMigration(processInstance.getId()); + assertThat(processInstanceMigrationValidationResult.isMigrationValid()).isTrue(); + + processInstanceMigrationBuilder.migrate(processInstance.getId()); + + //Confirm + executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version2ProcessDef.getId()); + tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()) + ); + + eventSubscriptions = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).list(); + assertThat(eventSubscriptions) + .extracting(EventSubscription::getEventName, EventSubscription::getActivityId, EventSubscription::getProcessDefinitionId) + .containsExactlyInAnyOrder(Tuple.tuple("eventSignal", "eventSubProcessStart", version2ProcessDef.getId())); + + completeProcessInstanceTasks(processInstance.getId()); + assertProcessEnded(processInstance.getId()); + } + @Test public void testMigrateSimpleActivityToActivityInsideNonInterruptingSignalEventSubProcessInNewDefinition() { ProcessDefinition procDefOneTask = deployProcessDefinition("my deploy", @@ -620,6 +702,90 @@ public void testMigrateNonInterruptingMessageEventSubProcessWithStartedSubProces assertProcessEnded(processInstance.getId()); } + @Test + public void testMigrateNonInterruptingMessageEventSubProcessWithTwoStartedSubProcess() { + //Deploy first version of the process + ProcessDefinition version1ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-message-event-subprocess.bpmn20.xml"); + + //Start an instance of the first version of the process for migration + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(version1ProcessDef.getKey()); + + //Deploy second version of the same process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-message-event-subprocess.bpmn20.xml"); + assertThat(version1ProcessDef.getId()).isNotEqualTo(version2ProcessDef.getId()); + + Execution messageSubscriptionExecution = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()) + .messageEventSubscriptionName("someMessage").singleResult(); + //Trigger the event to create the first sub process + runtimeService.messageEventReceived("someMessage", messageSubscriptionExecution.getId()); + //Trigger the event to create the second sub process + runtimeService.messageEventReceived("someMessage", messageSubscriptionExecution.getId()); + + //Confirm the state to migrate + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version1ProcessDef.getId()); + List tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()) + ); + List eventSubscriptions = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).list(); + assertThat(eventSubscriptions) + .extracting(EventSubscription::getEventName, EventSubscription::getActivityId, EventSubscription::getProcessDefinitionId) + .containsExactlyInAnyOrder(Tuple.tuple("someMessage", "eventSubProcessStart", version1ProcessDef.getId())); + + changeStateEventListener.clear(); + + //Migrate to the other processDefinition + ProcessInstanceMigrationBuilder processInstanceMigrationBuilder = processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()); + + ProcessInstanceMigrationValidationResult processInstanceMigrationValidationResult = processInstanceMigrationBuilder + .validateMigration(processInstance.getId()); + assertThat(processInstanceMigrationValidationResult.isMigrationValid()).isTrue(); + + processInstanceMigrationBuilder.migrate(processInstance.getId()); + + //Confirm + executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version2ProcessDef.getId()); + tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()) + ); + + eventSubscriptions = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).list(); + assertThat(eventSubscriptions) + .extracting(EventSubscription::getEventName, EventSubscription::getActivityId, EventSubscription::getProcessDefinitionId) + .containsExactlyInAnyOrder(Tuple.tuple("someMessage", "eventSubProcessStart", version2ProcessDef.getId())); + + completeProcessInstanceTasks(processInstance.getId()); + assertProcessEnded(processInstance.getId()); + } + @Test public void testMigrateSimpleActivityToActivityInsideNonInterruptingMessageEventSubProcessInNewDefinition() { ProcessDefinition procDefOneTask = deployProcessDefinition("my deploy", @@ -830,6 +996,98 @@ public void testMigrateNonInterruptingTimerEventSubProcessWithStartedSubProcess( assertProcessEnded(processInstance.getId()); } + @Test + public void testMigrateNonInterruptingTimerEventSubProcessWithTwoStartedSubProcess() { + //Deploy first version of the process + ProcessDefinition version1ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-timer-event-subprocess.bpmn20.xml"); + + //Start an instance of the first version of the process for migration + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(version1ProcessDef.getKey()); + + //Deploy second version of the same process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/non-interrupting-timer-event-subprocess.bpmn20.xml"); + assertThat(version1ProcessDef.getId()).isNotEqualTo(version2ProcessDef.getId()); + + //Trigger the timer job to create the first sub process + List timerJobs = managementService.createTimerJobQuery().processInstanceId(processInstance.getId()).list(); + assertThat(timerJobs).hasSize(1); + + managementService.moveTimerToExecutableJob(timerJobs.get(0).getId()); + managementService.executeJob(timerJobs.get(0).getId()); + + //Trigger the timer job to create the second sub process + timerJobs = managementService.createTimerJobQuery().processInstanceId(processInstance.getId()).list(); + assertThat(timerJobs).hasSize(1); + + managementService.moveTimerToExecutableJob(timerJobs.get(0).getId()); + managementService.executeJob(timerJobs.get(0).getId()); + + //Confirm the state to migrate + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version1ProcessDef.getId()); + List tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version1ProcessDef.getId()) + ); + + timerJobs = managementService.createTimerJobQuery().processInstanceId(processInstance.getId()).list(); + assertThat(timerJobs) + .extracting(Job::getProcessDefinitionId, Job::getElementId) + .containsExactlyInAnyOrder(Tuple.tuple(version1ProcessDef.getId(), "eventSubProcessStart")); + + changeStateEventListener.clear(); + + //Migrate to the other processDefinition + ProcessInstanceMigrationBuilder processInstanceMigrationBuilder = processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()); + + ProcessInstanceMigrationValidationResult processInstanceMigrationValidationResult = processInstanceMigrationBuilder + .validateMigration(processInstance.getId()); + assertThat(processInstanceMigrationValidationResult.isMigrationValid()).isTrue(); + + processInstanceMigrationBuilder.migrate(processInstance.getId()); + + //Confirm + executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).onlyChildExecutions().list(); + assertThat(executions) + .extracting(Execution::getActivityId) + .containsExactlyInAnyOrder( + "processTask", "eventSubProcessStart", "eventSubProcess", "eventSubProcessTask", "eventSubProcess", "eventSubProcessTask" + ); + assertThat(executions) + .extracting("processDefinitionId") + .containsOnly(version2ProcessDef.getId()); + tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list(); + assertThat(tasks) + .extracting(Task::getTaskDefinitionKey, Task::getProcessDefinitionId) + .containsExactlyInAnyOrder( + Tuple.tuple("processTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()), + Tuple.tuple("eventSubProcessTask", version2ProcessDef.getId()) + ); + + timerJobs = managementService.createTimerJobQuery().processInstanceId(processInstance.getId()).list(); + assertThat(timerJobs) + .extracting(Job::getProcessDefinitionId, Job::getElementId) + .containsExactlyInAnyOrder(Tuple.tuple(version2ProcessDef.getId(), "eventSubProcessStart")); + + completeProcessInstanceTasks(processInstance.getId()); + assertProcessEnded(processInstance.getId()); + } + @Test public void testMigrateSimpleActivityToActivityInsideNonInterruptingTimerEventSubProcessInNewDefinition() { ProcessDefinition procDefOneTask = deployProcessDefinition("my deploy",