diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ChangeActivityStateCmd.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ChangeActivityStateCmd.java index ba984b40448..cf975a57932 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ChangeActivityStateCmd.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ChangeActivityStateCmd.java @@ -33,10 +33,12 @@ public ChangeActivityStateCmd(ChangeActivityStateBuilderImpl changeActivityState @Override public Void execute(CommandContext commandContext) { - if (changeActivityStateBuilder.getMoveExecutionIdList().size() == 0 && changeActivityStateBuilder.getMoveActivityIdList().size() == 0) { - throw new FlowableIllegalArgumentException("No move execution or activity ids provided"); + if (changeActivityStateBuilder.getMoveExecutionIdList().isEmpty() && changeActivityStateBuilder.getMoveActivityIdList().isEmpty() + && changeActivityStateBuilder.getEnableActivityIdList().isEmpty()) { + + throw new FlowableIllegalArgumentException("No move execution or activity ids or enable activity ids provided"); - } else if (changeActivityStateBuilder.getMoveActivityIdList().size() > 0 && changeActivityStateBuilder.getProcessInstanceId() == null) { + } else if ((!changeActivityStateBuilder.getMoveActivityIdList().isEmpty() || !changeActivityStateBuilder.getEnableActivityIdList().isEmpty()) && changeActivityStateBuilder.getProcessInstanceId() == null) { throw new FlowableIllegalArgumentException("Process instance id is required"); } 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 2406f1b674b..58cc71e844e 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 @@ -76,6 +76,7 @@ import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityManager; import org.flowable.engine.impl.runtime.ChangeActivityStateBuilderImpl; +import org.flowable.engine.impl.runtime.EnableActivityIdContainer; import org.flowable.engine.impl.runtime.MoveActivityIdContainer; import org.flowable.engine.impl.runtime.MoveExecutionIdContainer; import org.flowable.engine.impl.util.CommandContextUtil; @@ -244,6 +245,18 @@ public List resolveMoveExecutionEntityContainers(C return moveExecutionEntityContainerList; } + + public List resolveEnableActivityContainers(ChangeActivityStateBuilderImpl changeActivityStateBuilder) { + List enableActivityContainerList = new ArrayList<>(); + if (!changeActivityStateBuilder.getEnableActivityIdList().isEmpty()) { + for (EnableActivityIdContainer enableActivityIdContainer : changeActivityStateBuilder.getEnableActivityIdList()) { + EnableActivityContainer enableActivityContainer = new EnableActivityContainer(enableActivityIdContainer.getActivityIds()); + enableActivityContainerList.add(enableActivityContainer); + } + } + + return enableActivityContainerList; + } protected ExecutionEntity resolveActiveExecution(String executionId, CommandContext commandContext) { ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); @@ -410,7 +423,6 @@ protected FlowElement resolveFlowElementFromBpmnModel(BpmnModel bpmnModel, Strin //-- Move container preparation section end protected void doMoveExecutionState(ProcessInstanceChangeState processInstanceChangeState, CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext); Map> activeEmbeddedSubProcesses = resolveActiveEmbeddedSubProcesses(processInstanceChangeState.getProcessInstanceId(), commandContext); processInstanceChangeState.setProcessInstanceActiveEmbeddedExecutions(activeEmbeddedSubProcesses); @@ -555,6 +567,31 @@ protected void doMoveExecutionState(ProcessInstanceChangeState processInstanceCh } processPendingEventSubProcessesStartEvents(processInstanceChangeState, commandContext); + + for (EnableActivityContainer enableActivityContainer : processInstanceChangeState.getEnableActivityContainers()) { + if (enableActivityContainer.getActivityIds() != null && !enableActivityContainer.getActivityIds().isEmpty()) { + BpmnModel bpmnModel = null; + ExecutionEntity parentExecution = executionEntityManager.findById(processInstanceChangeState.getProcessInstanceId()); + if (processInstanceChangeState.getProcessDefinitionToMigrateTo() != null) { + bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstanceChangeState.getProcessDefinitionToMigrateTo().getId()); + + } else { + bpmnModel = ProcessDefinitionUtil.getBpmnModel(parentExecution.getProcessDefinitionId()); + } + + ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext); + ProcessInstanceHelper processInstanceHelper = processEngineConfiguration.getProcessInstanceHelper(); + + for (String enableActivityId : enableActivityContainer.getActivityIds()) { + FlowElement enableFlowElement = bpmnModel.getFlowElement(enableActivityId); + if (enableFlowElement == null) { + throw new FlowableException("could not find element for activity id " + enableActivityId); + } + + processInstanceHelper.processEventSubProcessStartEvent(enableFlowElement, parentExecution, processEngineConfiguration, commandContext); + } + } + } } protected void processPendingEventSubProcessesStartEvents(ProcessInstanceChangeState processInstanceChangeState, CommandContext commandContext) { diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/DefaultDynamicStateManager.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/DefaultDynamicStateManager.java index aa4a78d5356..74921ebce50 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/DefaultDynamicStateManager.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/DefaultDynamicStateManager.java @@ -35,12 +35,23 @@ public class DefaultDynamicStateManager extends AbstractDynamicStateManager impl public void moveExecutionState(ChangeActivityStateBuilderImpl changeActivityStateBuilder, CommandContext commandContext) { List moveExecutionEntityContainerList = resolveMoveExecutionEntityContainers(changeActivityStateBuilder, changeActivityStateBuilder.getProcessInstanceVariables(), commandContext); - List executions = moveExecutionEntityContainerList.iterator().next().getExecutions(); - String processInstanceId = executions.iterator().next().getProcessInstanceId(); + List executions = null; + if (!moveExecutionEntityContainerList.isEmpty()) { + executions = moveExecutionEntityContainerList.iterator().next().getExecutions(); + } + + List enableActivityContainerList = resolveEnableActivityContainers(changeActivityStateBuilder); + String processInstanceId = null; + if (executions != null && !executions.isEmpty()) { + processInstanceId = executions.iterator().next().getProcessInstanceId(); + } else { + processInstanceId = changeActivityStateBuilder.getProcessInstanceId(); + } ProcessInstanceChangeState processInstanceChangeState = new ProcessInstanceChangeState() .setProcessInstanceId(processInstanceId) .setMoveExecutionEntityContainers(moveExecutionEntityContainerList) + .setEnableActivityContainers(enableActivityContainerList) .setLocalVariables(changeActivityStateBuilder.getLocalVariables()) .setProcessInstanceVariables(changeActivityStateBuilder.getProcessInstanceVariables()); diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/EnableActivityContainer.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/EnableActivityContainer.java new file mode 100644 index 00000000000..03535f3720c --- /dev/null +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/EnableActivityContainer.java @@ -0,0 +1,28 @@ +/* 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.flowable.engine.impl.dynamic; + +import java.util.List; + +public class EnableActivityContainer { + + protected List activityIds; + + public EnableActivityContainer(List activityIds) { + this.activityIds = activityIds; + } + + public List getActivityIds() { + return activityIds; + } +} diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/ProcessInstanceChangeState.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/ProcessInstanceChangeState.java index 44d5aee8d99..aaca70aae90 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/ProcessInstanceChangeState.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/ProcessInstanceChangeState.java @@ -33,6 +33,7 @@ public class ProcessInstanceChangeState { protected Map> localVariables = new HashMap<>(); protected Map> processInstanceActiveEmbeddedExecutions; protected List moveExecutionEntityContainers; + protected List enableActivityContainers; protected HashMap createdEmbeddedSubProcess = new HashMap<>(); protected HashMap createdMultiInstanceRootExecution = new HashMap<>(); protected HashMap pendingEventSubProcessesStartEvents = new HashMap<>(); @@ -80,6 +81,15 @@ public ProcessInstanceChangeState setLocalVariables(Map getEnableActivityContainers() { + return enableActivityContainers; + } + + public ProcessInstanceChangeState setEnableActivityContainers(List enableActivityContainers) { + this.enableActivityContainers = enableActivityContainers; + return this; + } + public List getMoveExecutionEntityContainers() { return moveExecutionEntityContainers; } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationBuilderImpl.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationBuilderImpl.java index bbce45a0a0b..300e9dc23b1 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationBuilderImpl.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationBuilderImpl.java @@ -19,6 +19,7 @@ import org.flowable.common.engine.api.FlowableException; import org.flowable.engine.ProcessMigrationService; import org.flowable.engine.migration.ActivityMigrationMapping; +import org.flowable.engine.migration.EnableActivityMapping; import org.flowable.engine.migration.ProcessInstanceMigrationBuilder; import org.flowable.engine.migration.ProcessInstanceMigrationDocument; import org.flowable.engine.migration.ProcessInstanceMigrationValidationResult; @@ -114,6 +115,12 @@ public ProcessInstanceMigrationBuilder addActivityMigrationMapping(ActivityMigra this.migrationDocumentBuilder.addActivityMigrationMapping(mapping); return this; } + + @Override + public ProcessInstanceMigrationBuilder addEnableEventSubProcessStartEvent(EnableActivityMapping mapping) { + this.migrationDocumentBuilder.addEnableActivityMapping(mapping); + return this; + } @Override public ProcessInstanceMigrationBuilder withProcessInstanceVariable(String variableName, Object variableValue) { diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentBuilderImpl.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentBuilderImpl.java index 52310f28e52..e976a35762b 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentBuilderImpl.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentBuilderImpl.java @@ -20,6 +20,7 @@ import org.flowable.common.engine.api.FlowableException; import org.flowable.engine.migration.ActivityMigrationMapping; +import org.flowable.engine.migration.EnableActivityMapping; import org.flowable.engine.migration.ProcessInstanceMigrationDocument; import org.flowable.engine.migration.ProcessInstanceMigrationDocumentBuilder; import org.flowable.engine.migration.Script; @@ -35,6 +36,7 @@ public class ProcessInstanceMigrationDocumentBuilderImpl implements ProcessInsta protected Integer migrateToProcessDefinitionVersion; protected String migrateToProcessDefinitionTenantId; protected List activityMigrationMappings = new ArrayList<>(); + protected List enableActivityMappings = new ArrayList<>(); protected Map processInstanceVariables = new HashMap<>(); protected Script preUpgradeScript; protected String preUpgradeJavaDelegate; @@ -109,6 +111,18 @@ public ProcessInstanceMigrationDocumentBuilder addActivityMigrationMapping(Activ this.activityMigrationMappings.add(activityMigrationMapping); return this; } + + @Override + public ProcessInstanceMigrationDocumentBuilder addEnableActivityMappings(List enableActivityMappings) { + this.enableActivityMappings.addAll(enableActivityMappings); + return this; + } + + @Override + public ProcessInstanceMigrationDocumentBuilder addEnableActivityMapping(EnableActivityMapping enableActivityMapping) { + this.enableActivityMappings.add(enableActivityMapping); + return this; + } @Override public ProcessInstanceMigrationDocumentBuilder addProcessInstanceVariable(String variableName, Object variableValue) { @@ -156,6 +170,7 @@ public ProcessInstanceMigrationDocument build() { document.setPostUpgradeJavaDelegateExpression(postUpgradeJavaDelegateExpression); } document.setActivityMigrationMappings(activityMigrationMappings); + document.setEnableActivityMappings(enableActivityMappings); document.setProcessInstanceVariables(processInstanceVariables); return document; diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java index 4b4489ebc36..b4e16635ff1 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentImpl.java @@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils; import org.flowable.common.engine.api.FlowableException; import org.flowable.engine.migration.ActivityMigrationMapping; +import org.flowable.engine.migration.EnableActivityMapping; import org.flowable.engine.migration.ProcessInstanceMigrationDocument; import org.flowable.engine.migration.ProcessInstanceMigrationDocumentConverter; import org.flowable.engine.migration.Script; @@ -40,6 +41,7 @@ public class ProcessInstanceMigrationDocumentImpl implements ProcessInstanceMigr protected Integer migrateToProcessDefinitionVersion; protected String migrateToProcessDefinitionTenantId; protected List activityMigrationMappings; + protected List enableActivityMappings; protected Map> activitiesLocalVariables; protected Map processInstanceVariables; protected Script preUpgradeScript; @@ -199,6 +201,10 @@ public void setActivityMigrationMappings(List activity throw new FlowableException("From activity '" + Arrays.toString(duplicates.toArray()) + "' is mapped more than once"); } } + + public void setEnableActivityMappings(List enableActivityMappings) { + this.enableActivityMappings = enableActivityMappings; + } protected static List findDuplicatedFromActivityIds(List activityMigrationMappings) { //Frequency Map @@ -245,6 +251,11 @@ protected static Map> buildActivitiesLocalVariablesM public List getActivityMigrationMappings() { return activityMigrationMappings; } + + @Override + public List getEnableActivityMappings() { + return enableActivityMappings; + } @Override public Map> getActivitiesLocalVariables() { diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationManagerImpl.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationManagerImpl.java index 81b0df07676..1dbf665d5f7 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationManagerImpl.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationManagerImpl.java @@ -60,6 +60,7 @@ import org.flowable.engine.impl.delegate.ActivityBehaviorInvocation; import org.flowable.engine.impl.delegate.invocation.JavaDelegateInvocation; import org.flowable.engine.impl.dynamic.AbstractDynamicStateManager; +import org.flowable.engine.impl.dynamic.EnableActivityContainer; import org.flowable.engine.impl.dynamic.MoveExecutionEntityContainer; import org.flowable.engine.impl.dynamic.ProcessInstanceChangeState; import org.flowable.engine.impl.history.HistoryManager; @@ -74,6 +75,7 @@ import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.impl.util.ProcessDefinitionUtil; import org.flowable.engine.migration.ActivityMigrationMapping; +import org.flowable.engine.migration.EnableActivityMapping; import org.flowable.engine.migration.ProcessInstanceBatchMigrationResult; import org.flowable.engine.migration.ProcessInstanceMigrationCallback; import org.flowable.engine.migration.ProcessInstanceMigrationDocument; @@ -435,11 +437,20 @@ protected void doMigrateProcessInstance(ProcessInstance processInstance, Process builder, document.getProcessInstanceVariables(), commandContext); moveExecutionEntityContainerList.addAll(moveExecutionEntityContainers); } + + List enableActivityContainerList = new ArrayList<>(); + if (!document.getEnableActivityMappings().isEmpty()) { + for (EnableActivityMapping enableActivityMapping : document.getEnableActivityMappings()) { + EnableActivityContainer enableActivityContainer = new EnableActivityContainer(Collections.singletonList(enableActivityMapping.getActivityId())); + enableActivityContainerList.add(enableActivityContainer); + } + } ProcessInstanceChangeState processInstanceChangeState = new ProcessInstanceChangeState() .setProcessInstanceId(processInstance.getId()) .setProcessDefinitionToMigrateTo(procDefToMigrateTo) .setMoveExecutionEntityContainers(moveExecutionEntityContainerList) + .setEnableActivityContainers(enableActivityContainerList) .setProcessInstanceVariables(document.getProcessInstanceVariables()) .setLocalVariables(document.getActivitiesLocalVariables()); diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java index 95b9560395d..0aeb7bdd093 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java @@ -31,6 +31,7 @@ public class ChangeActivityStateBuilderImpl implements ChangeActivityStateBuilde protected String processInstanceId; protected List moveExecutionIdList = new ArrayList<>(); protected List moveActivityIdList = new ArrayList<>(); + protected List enableActivityIdList = new ArrayList<>(); protected Map processVariables = new HashMap<>(); protected Map> localVariables = new HashMap<>(); @@ -170,6 +171,13 @@ public ChangeActivityStateBuilder moveSingleActivityIdToSubProcessInstanceActivi moveActivityIdList.add(moveActivityIdsContainer); return this; } + + @Override + public ChangeActivityStateBuilder enableEventSubProcessStartEvent(String eventSubProcessStartEventId) { + EnableActivityIdContainer enableActivityIdContainer = new EnableActivityIdContainer(eventSubProcessStartEventId); + enableActivityIdList.add(enableActivityIdContainer); + return this; + } @Override public ChangeActivityStateBuilder processVariable(String processVariableName, Object processVariableValue) { @@ -238,6 +246,10 @@ public List getMoveActivityIdList() { return moveActivityIdList; } + public List getEnableActivityIdList() { + return enableActivityIdList; + } + public Map getProcessInstanceVariables() { return processVariables; } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/EnableActivityIdContainer.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/EnableActivityIdContainer.java new file mode 100644 index 00000000000..9593b5a4e51 --- /dev/null +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/EnableActivityIdContainer.java @@ -0,0 +1,37 @@ +/* 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.flowable.engine.impl.runtime; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * @author Tijs Rademakers + */ +public class EnableActivityIdContainer { + + protected List activityIds; + + public EnableActivityIdContainer(String singleActivityId) { + this.activityIds = Collections.singletonList(singleActivityId); + } + + public EnableActivityIdContainer(List activityIds) { + this.activityIds = activityIds; + } + + public List getActivityIds() { + return Optional.ofNullable(activityIds).orElse(Collections.emptyList()); + } +} diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java index 78a27a074be..47a774f9f53 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java @@ -336,52 +336,11 @@ public void processEventSubProcess(ExecutionEntity parentExecution, EventSubProc if (!(subElement instanceof StartEvent)) { continue; } - - StartEvent startEvent = (StartEvent) subElement; - if (CollectionUtil.isEmpty(startEvent.getEventDefinitions())) { - List eventTypeElements = startEvent.getExtensionElements().get("eventType"); - if (eventTypeElements != null && !eventTypeElements.isEmpty()) { - String eventType = eventTypeElements.get(0).getElementText(); - if (StringUtils.isNotEmpty(eventType)) { - ExecutionEntity eventRegistryExecution = processEngineConfiguration.getExecutionEntityManager().createChildExecution(parentExecution); - eventRegistryExecution.setCurrentFlowElement(startEvent); - eventRegistryExecution.setEventScope(true); - eventRegistryExecution.setActive(false); - - EventSubscriptionEntity eventSubscription = (EventSubscriptionEntity) processEngineConfiguration.getEventSubscriptionServiceConfiguration() - .getEventSubscriptionService().createEventSubscriptionBuilder() - .eventType(eventType) - .executionId(eventRegistryExecution.getId()) - .processInstanceId(eventRegistryExecution.getProcessInstanceId()) - .activityId(eventRegistryExecution.getCurrentActivityId()) - .processDefinitionId(eventRegistryExecution.getProcessDefinitionId()) - .scopeType(ScopeTypes.BPMN) - .tenantId(eventRegistryExecution.getTenantId()) - .configuration(CorrelationUtil.getCorrelationKey(BpmnXMLConstants.ELEMENT_EVENT_CORRELATION_PARAMETER, commandContext, eventRegistryExecution)) - .create(); - - CountingEntityUtil.handleInsertEventSubscriptionEntityCount(eventSubscription); - } - } - - continue; - } - - EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0); - if (eventDefinition instanceof MessageEventDefinition) { - handleMessageEventSubscription(eventDefinition, startEvent, parentExecution, messageEventSubscriptions, processEngineConfiguration, commandContext); - - } else if (eventDefinition instanceof SignalEventDefinition) { - handleSignalEventSubscription(eventDefinition, startEvent, parentExecution, signalEventSubscriptions, processEngineConfiguration, commandContext); - - } else if (eventDefinition instanceof TimerEventDefinition) { - handleTimerEvent(eventDefinition, startEvent, parentExecution, processEngineConfiguration); - } else if (eventDefinition instanceof VariableListenerEventDefinition) { - handleVariableListenerEventSubscription(eventDefinition, startEvent, parentExecution, processEngineConfiguration, commandContext); - } + processEventSubProcessStartEvent(subElement, parentExecution, messageEventSubscriptions, + signalEventSubscriptions, processEngineConfiguration, commandContext); } - + FlowableEventDispatcher eventDispatcher = processEngineConfiguration.getEventDispatcher(); if (eventDispatcher != null && eventDispatcher.isEnabled()) { for (EventSubscriptionEntity messageEventSubscription : messageEventSubscriptions) { @@ -400,6 +359,61 @@ public void processEventSubProcess(ExecutionEntity parentExecution, EventSubProc } } + public void processEventSubProcessStartEvent(FlowElement subElement, ExecutionEntity parentExecution, + ProcessEngineConfigurationImpl processEngineConfiguration, CommandContext commandContext) { + + processEventSubProcessStartEvent(subElement, parentExecution, null, null, processEngineConfiguration, commandContext); + } + + public void processEventSubProcessStartEvent(FlowElement subElement, ExecutionEntity parentExecution, + List messageEventSubscriptions, List signalEventSubscriptions, + ProcessEngineConfigurationImpl processEngineConfiguration, CommandContext commandContext) { + + StartEvent startEvent = (StartEvent) subElement; + if (CollectionUtil.isEmpty(startEvent.getEventDefinitions())) { + List eventTypeElements = startEvent.getExtensionElements().get("eventType"); + if (eventTypeElements != null && !eventTypeElements.isEmpty()) { + String eventType = eventTypeElements.get(0).getElementText(); + if (StringUtils.isNotEmpty(eventType)) { + ExecutionEntity eventRegistryExecution = processEngineConfiguration.getExecutionEntityManager().createChildExecution(parentExecution); + eventRegistryExecution.setCurrentFlowElement(startEvent); + eventRegistryExecution.setEventScope(true); + eventRegistryExecution.setActive(false); + + EventSubscriptionEntity eventSubscription = (EventSubscriptionEntity) processEngineConfiguration.getEventSubscriptionServiceConfiguration() + .getEventSubscriptionService().createEventSubscriptionBuilder() + .eventType(eventType) + .executionId(eventRegistryExecution.getId()) + .processInstanceId(eventRegistryExecution.getProcessInstanceId()) + .activityId(eventRegistryExecution.getCurrentActivityId()) + .processDefinitionId(eventRegistryExecution.getProcessDefinitionId()) + .scopeType(ScopeTypes.BPMN) + .tenantId(eventRegistryExecution.getTenantId()) + .configuration(CorrelationUtil.getCorrelationKey(BpmnXMLConstants.ELEMENT_EVENT_CORRELATION_PARAMETER, commandContext, eventRegistryExecution)) + .create(); + + CountingEntityUtil.handleInsertEventSubscriptionEntityCount(eventSubscription); + } + } + + return; + } + + EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0); + if (eventDefinition instanceof MessageEventDefinition) { + handleMessageEventSubscription(eventDefinition, startEvent, parentExecution, messageEventSubscriptions, processEngineConfiguration, commandContext); + + } else if (eventDefinition instanceof SignalEventDefinition) { + handleSignalEventSubscription(eventDefinition, startEvent, parentExecution, signalEventSubscriptions, processEngineConfiguration, commandContext); + + } else if (eventDefinition instanceof TimerEventDefinition) { + handleTimerEvent(eventDefinition, startEvent, parentExecution, processEngineConfiguration); + + } else if (eventDefinition instanceof VariableListenerEventDefinition) { + handleVariableListenerEventSubscription(eventDefinition, startEvent, parentExecution, processEngineConfiguration, commandContext); + } + } + protected void handleMessageEventSubscription(EventDefinition eventDefinition, StartEvent startEvent, ExecutionEntity parentExecution, List messageEventSubscriptions, ProcessEngineConfigurationImpl processEngineConfiguration, CommandContext commandContext) { @@ -427,7 +441,9 @@ protected void handleMessageEventSubscription(EventDefinition eventDefinition, S .create(); CountingEntityUtil.handleInsertEventSubscriptionEntityCount(eventSubscription); - messageEventSubscriptions.add(eventSubscription); + if (messageEventSubscriptions != null) { + messageEventSubscriptions.add(eventSubscription); + } messageExecution.getEventSubscriptions().add(eventSubscription); } @@ -462,7 +478,9 @@ protected void handleSignalEventSubscription(EventDefinition eventDefinition, St .create(); CountingEntityUtil.handleInsertEventSubscriptionEntityCount(eventSubscription); - signalEventSubscriptions.add(eventSubscription); + if (signalEventSubscriptions != null) { + signalEventSubscriptions.add(eventSubscription); + } signalExecution.getEventSubscriptions().add(eventSubscription); } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ActivityMigrationMapping.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ActivityMigrationMapping.java index a4019dc66fd..4c08caacee2 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ActivityMigrationMapping.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ActivityMigrationMapping.java @@ -18,9 +18,6 @@ import java.util.List; import java.util.Map; -/** - * @author Dennis - */ public abstract class ActivityMigrationMapping { protected String toCallActivityId; diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/EnableActivityMapping.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/EnableActivityMapping.java new file mode 100644 index 00000000000..3256b56b365 --- /dev/null +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/EnableActivityMapping.java @@ -0,0 +1,41 @@ +/* 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.flowable.engine.migration; + +public abstract class EnableActivityMapping { + + public abstract String getActivityId(); + + public static EnableActivityMapping.EnableMapping enable(String activityId) { + return new EnableMapping(activityId); + } + + public static class EnableMapping extends EnableActivityMapping { + + public String activityId; + + public EnableMapping(String activityId) { + this.activityId = activityId; + } + + @Override + public String getActivityId() { + return activityId; + } + + @Override + public String toString() { + return "EnableMapping{" + "activityId='" + activityId + "\'}"; + } + } +} \ No newline at end of file diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationBuilder.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationBuilder.java index 48a241c1e9a..54d077828de 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationBuilder.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationBuilder.java @@ -122,6 +122,15 @@ public interface ProcessInstanceMigrationBuilder { * @see ActivityMigrationMapping */ ProcessInstanceMigrationBuilder addActivityMigrationMapping(ActivityMigrationMapping mapping); + + /** + * Adds an event sub process start event to enable for the migration. + * + * @param mapping + * @return + * @see EnableActivityMapping + */ + ProcessInstanceMigrationBuilder addEnableEventSubProcessStartEvent(EnableActivityMapping mapping); /** * Specifies a process instance variable that will also be available during the process migration (ie. to resolve callActivity calledElement expressions of the new process definition - if any) diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocument.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocument.java index a49ca668e1b..f8899525fe3 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocument.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocument.java @@ -43,6 +43,8 @@ public interface ProcessInstanceMigrationDocument { String getPostUpgradeJavaDelegateExpression(); List getActivityMigrationMappings(); + + List getEnableActivityMappings(); Map> getActivitiesLocalVariables(); diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentBuilder.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentBuilder.java index 4fd0d80221c..53c1debf81e 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentBuilder.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentBuilder.java @@ -43,6 +43,10 @@ public interface ProcessInstanceMigrationDocumentBuilder { ProcessInstanceMigrationDocumentBuilder addActivityMigrationMappings(List activityMigrationMappings); ProcessInstanceMigrationDocumentBuilder addActivityMigrationMapping(ActivityMigrationMapping activityMigrationMapping); + + ProcessInstanceMigrationDocumentBuilder addEnableActivityMappings(List enableActivityMappings); + + ProcessInstanceMigrationDocumentBuilder addEnableActivityMapping(EnableActivityMapping enableActivityMapping); ProcessInstanceMigrationDocumentBuilder addProcessInstanceVariable(String variableName, Object variableValue); diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConstants.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConstants.java index 61ee56f5850..6554b5f22ab 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConstants.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConstants.java @@ -28,6 +28,7 @@ public interface ProcessInstanceMigrationDocumentConstants { String TO_ACTIVITY_ID_JSON_PROPERTY = "toActivityId"; String TO_ACTIVITY_IDS_JSON_PROPERTY = "toActivityIds"; String NEW_ASSIGNEE_JSON_PROPERTY = "newAssignee"; + String ACTIVITY_ID_JSON_PROPERTY = "activityId"; String IN_SUB_PROCESS_OF_CALL_ACTIVITY_ID_JSON_PROPERTY = "inSubProcessOfCallActivityId"; String CALL_ACTIVITY_PROCESS_DEFINITION_VERSION_JSON_PROPERTY = "callActivityProcessDefinitionVersion"; @@ -43,6 +44,7 @@ public interface ProcessInstanceMigrationDocumentConstants { String SCRIPT = "script"; String ACTIVITY_MAPPINGS_JSON_SECTION = "activityMappings"; + String ENABLE_ACTIVITY_MAPPINGS_JSON_SECTION = "enableActivityMappings"; String LOCAL_VARIABLES_JSON_SECTION = "localVariables"; String PROCESS_INSTANCE_VARIABLES_JSON_SECTION = "processInstanceVariables"; diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConverter.java b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConverter.java index e07c86b54f5..8d03379c782 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConverter.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/migration/ProcessInstanceMigrationDocumentConverter.java @@ -12,30 +12,6 @@ */ package org.flowable.engine.migration; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.ACTIVITY_MAPPINGS_JSON_SECTION; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.CALL_ACTIVITY_PROCESS_DEFINITION_VERSION_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_IDS_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.IN_PARENT_PROCESS_OF_CALL_ACTIVITY_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.IN_SUB_PROCESS_OF_CALL_ACTIVITY_ID_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.LANGUAGE; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.LOCAL_VARIABLES_JSON_SECTION; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.NEW_ASSIGNEE_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_JAVA_DELEGATE; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_JAVA_DELEGATE_EXPRESSION; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_SCRIPT; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_JAVA_DELEGATE; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_JAVA_DELEGATE_EXPRESSION; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_SCRIPT; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.PROCESS_INSTANCE_VARIABLES_JSON_SECTION; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.SCRIPT; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_IDS_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_ID_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_KEY_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_TENANT_ID_JSON_PROPERTY; -import static org.flowable.engine.migration.ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_VERSION_JSON_PROPERTY; - import java.io.IOException; import java.util.HashMap; import java.util.List; @@ -85,55 +61,60 @@ public static JsonNode convertToJson(ProcessInstanceMigrationDocument processIns ObjectNode documentNode = objectMapper.createObjectNode(); if (processInstanceMigrationDocument.getMigrateToProcessDefinitionId() != null) { - documentNode.put(TO_PROCESS_DEFINITION_ID_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionId()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_ID_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionId()); } if (processInstanceMigrationDocument.getMigrateToProcessDefinitionKey() != null) { - documentNode.put(TO_PROCESS_DEFINITION_KEY_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionKey()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_KEY_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionKey()); } if (processInstanceMigrationDocument.getMigrateToProcessDefinitionVersion() != null) { - documentNode.put(TO_PROCESS_DEFINITION_VERSION_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionVersion()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_VERSION_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionVersion()); } if (processInstanceMigrationDocument.getMigrateToProcessDefinitionTenantId() != null) { - documentNode.put(TO_PROCESS_DEFINITION_TENANT_ID_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionTenantId()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_TENANT_ID_JSON_PROPERTY, processInstanceMigrationDocument.getMigrateToProcessDefinitionTenantId()); } JsonNode preUpgradeScriptNode = convertToJsonUpgradeScript(processInstanceMigrationDocument.getPreUpgradeScript(), objectMapper); if (preUpgradeScriptNode != null && !preUpgradeScriptNode.isNull()) { - documentNode.set(PRE_UPGRADE_SCRIPT, preUpgradeScriptNode); + documentNode.set(ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_SCRIPT, preUpgradeScriptNode); } if (processInstanceMigrationDocument.getPreUpgradeJavaDelegate() != null) { - documentNode.put(PRE_UPGRADE_JAVA_DELEGATE, processInstanceMigrationDocument.getPreUpgradeJavaDelegate()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_JAVA_DELEGATE, processInstanceMigrationDocument.getPreUpgradeJavaDelegate()); } if (processInstanceMigrationDocument.getPreUpgradeJavaDelegateExpression() != null) { - documentNode.put(PRE_UPGRADE_JAVA_DELEGATE_EXPRESSION, processInstanceMigrationDocument.getPreUpgradeJavaDelegateExpression()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_JAVA_DELEGATE_EXPRESSION, processInstanceMigrationDocument.getPreUpgradeJavaDelegateExpression()); } JsonNode postUpgradeScriptNode = convertToJsonUpgradeScript(processInstanceMigrationDocument.getPostUpgradeScript(), objectMapper); if (postUpgradeScriptNode != null && !postUpgradeScriptNode.isNull()) { - documentNode.set(POST_UPGRADE_SCRIPT, postUpgradeScriptNode); + documentNode.set(ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_SCRIPT, postUpgradeScriptNode); } if (processInstanceMigrationDocument.getPostUpgradeJavaDelegate() != null) { - documentNode.put(POST_UPGRADE_JAVA_DELEGATE, processInstanceMigrationDocument.getPostUpgradeJavaDelegate()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_JAVA_DELEGATE, processInstanceMigrationDocument.getPostUpgradeJavaDelegate()); } if (processInstanceMigrationDocument.getPostUpgradeJavaDelegateExpression() != null) { - documentNode.put(POST_UPGRADE_JAVA_DELEGATE_EXPRESSION, processInstanceMigrationDocument.getPostUpgradeJavaDelegateExpression()); + documentNode.put(ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_JAVA_DELEGATE_EXPRESSION, processInstanceMigrationDocument.getPostUpgradeJavaDelegateExpression()); } ArrayNode mappingNodes = convertToJsonActivityMigrationMappings(processInstanceMigrationDocument.getActivityMigrationMappings()); if (mappingNodes != null && !mappingNodes.isNull()) { - documentNode.set(ACTIVITY_MAPPINGS_JSON_SECTION, mappingNodes); + documentNode.set(ProcessInstanceMigrationDocumentConstants.ACTIVITY_MAPPINGS_JSON_SECTION, mappingNodes); + } + + ArrayNode enableActivityNodes = convertToJsonEnableActivityMappings(processInstanceMigrationDocument.getEnableActivityMappings()); + if (enableActivityNodes != null && !enableActivityNodes.isNull()) { + documentNode.set(ProcessInstanceMigrationDocumentConstants.ENABLE_ACTIVITY_MAPPINGS_JSON_SECTION, enableActivityNodes); } JsonNode processInstanceVariablesNode = convertToJsonProcessInstanceVariables(processInstanceMigrationDocument, objectMapper); if (processInstanceVariablesNode != null && !processInstanceVariablesNode.isNull()) { - documentNode.set(PROCESS_INSTANCE_VARIABLES_JSON_SECTION, processInstanceVariablesNode); + documentNode.set(ProcessInstanceMigrationDocumentConstants.PROCESS_INSTANCE_VARIABLES_JSON_SECTION, processInstanceVariablesNode); } return documentNode; @@ -163,6 +144,17 @@ protected static ArrayNode convertToJsonActivityMigrationMappings(List enableActivityMappings) { + ArrayNode mappingsArray = objectMapper.createArrayNode(); + + for (EnableActivityMapping mapping : enableActivityMappings) { + ObjectNode mappingNode = mappingsArray.addObject(); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.ACTIVITY_ID_JSON_PROPERTY, mapping.getActivityId()); + } + + return mappingsArray; + } public static ProcessInstanceMigrationDocument convertFromJson(String jsonProcessInstanceMigrationDocument) { @@ -170,62 +162,65 @@ public static ProcessInstanceMigrationDocument convertFromJson(String jsonProces JsonNode rootNode = objectMapper.readTree(jsonProcessInstanceMigrationDocument); ProcessInstanceMigrationDocumentBuilderImpl documentBuilder = new ProcessInstanceMigrationDocumentBuilderImpl(); - String processDefinitionId = Optional.ofNullable(rootNode.get(TO_PROCESS_DEFINITION_ID_JSON_PROPERTY)) + String processDefinitionId = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_ID_JSON_PROPERTY)) .map(JsonNode::textValue).orElse(null); documentBuilder.setProcessDefinitionToMigrateTo(processDefinitionId); - String processDefinitionKey = Optional.ofNullable(rootNode.get(TO_PROCESS_DEFINITION_KEY_JSON_PROPERTY)) + String processDefinitionKey = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_KEY_JSON_PROPERTY)) .map(JsonNode::textValue).orElse(null); - Integer processDefinitionVersion = (Integer) Optional.ofNullable(rootNode.get(TO_PROCESS_DEFINITION_VERSION_JSON_PROPERTY)) + Integer processDefinitionVersion = (Integer) Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_VERSION_JSON_PROPERTY)) .map(JsonNode::numberValue).orElse(null); documentBuilder.setProcessDefinitionToMigrateTo(processDefinitionKey, processDefinitionVersion); - String processDefinitionTenantId = Optional.ofNullable(rootNode.get(TO_PROCESS_DEFINITION_TENANT_ID_JSON_PROPERTY)) + String processDefinitionTenantId = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.TO_PROCESS_DEFINITION_TENANT_ID_JSON_PROPERTY)) .map(JsonNode::textValue).orElse(null); documentBuilder.setTenantId(processDefinitionTenantId); - JsonNode preUpgradeScriptNode = rootNode.get(PRE_UPGRADE_SCRIPT); + JsonNode preUpgradeScriptNode = rootNode.get(ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_SCRIPT); if (preUpgradeScriptNode != null) { - String language = Optional.ofNullable(preUpgradeScriptNode.get(LANGUAGE)).map(JsonNode::asText).orElse("javascript"); - String script = Optional.ofNullable(preUpgradeScriptNode.get(SCRIPT)).map(JsonNode::asText).orElse("javascript"); + String language = Optional.ofNullable(preUpgradeScriptNode.get(ProcessInstanceMigrationDocumentConstants.LANGUAGE)).map(JsonNode::asText).orElse("javascript"); + String script = Optional.ofNullable(preUpgradeScriptNode.get(ProcessInstanceMigrationDocumentConstants.SCRIPT)).map(JsonNode::asText).orElse("javascript"); documentBuilder.setPreUpgradeScript(new Script(language, script)); } - String javaDelegateClassName = Optional.ofNullable(rootNode.get(PRE_UPGRADE_JAVA_DELEGATE)) + String javaDelegateClassName = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_JAVA_DELEGATE)) .map(JsonNode::textValue).orElse(null); documentBuilder.setPreUpgradeJavaDelegate(javaDelegateClassName); - String expression = Optional.ofNullable(rootNode.get(PRE_UPGRADE_JAVA_DELEGATE_EXPRESSION)) + String expression = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.PRE_UPGRADE_JAVA_DELEGATE_EXPRESSION)) .map(JsonNode::textValue).orElse(null); documentBuilder.setPreUpgradeJavaDelegateExpression(expression); - JsonNode postUpgradeScriptNode = rootNode.get(POST_UPGRADE_SCRIPT); + JsonNode postUpgradeScriptNode = rootNode.get(ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_SCRIPT); if (postUpgradeScriptNode != null) { - String language = Optional.ofNullable(postUpgradeScriptNode.get(LANGUAGE)).map(JsonNode::asText).orElse("javascript"); - String script = Optional.ofNullable(postUpgradeScriptNode.get(SCRIPT)).map(JsonNode::asText).orElse("javascript"); + String language = Optional.ofNullable(postUpgradeScriptNode.get(ProcessInstanceMigrationDocumentConstants.LANGUAGE)).map(JsonNode::asText).orElse("javascript"); + String script = Optional.ofNullable(postUpgradeScriptNode.get(ProcessInstanceMigrationDocumentConstants.SCRIPT)).map(JsonNode::asText).orElse("javascript"); documentBuilder.setPostUpgradeScript(new Script(language, script)); } - String postJavaDelegateClassName = Optional.ofNullable(rootNode.get(POST_UPGRADE_JAVA_DELEGATE)) + String postJavaDelegateClassName = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_JAVA_DELEGATE)) .map(JsonNode::textValue).orElse(null); documentBuilder.setPostUpgradeJavaDelegate(postJavaDelegateClassName); - String postExpression = Optional.ofNullable(rootNode.get(POST_UPGRADE_JAVA_DELEGATE_EXPRESSION)) + String postExpression = Optional.ofNullable(rootNode.get(ProcessInstanceMigrationDocumentConstants.POST_UPGRADE_JAVA_DELEGATE_EXPRESSION)) .map(JsonNode::textValue).orElse(null); documentBuilder.setPostUpgradeJavaDelegateExpression(postExpression); - JsonNode activityMigrationMappings = rootNode.get(ACTIVITY_MAPPINGS_JSON_SECTION); + JsonNode activityMigrationMappings = rootNode.get(ProcessInstanceMigrationDocumentConstants.ACTIVITY_MAPPINGS_JSON_SECTION); if (activityMigrationMappings != null) { for (JsonNode mappingNode : activityMigrationMappings) { Class mappingClass = null; - if (isSingleTextValue.test(mappingNode.get(FROM_ACTIVITY_ID_JSON_PROPERTY)) && isSingleTextValue.test(mappingNode.get(TO_ACTIVITY_ID_JSON_PROPERTY))) { + if (isSingleTextValue.test(mappingNode.get(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY)) && + isSingleTextValue.test(mappingNode.get(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY))) { mappingClass = ActivityMigrationMapping.OneToOneMapping.class; } - if (isSingleTextValue.test(mappingNode.get(FROM_ACTIVITY_ID_JSON_PROPERTY)) && isMultiValue.test(mappingNode.get(TO_ACTIVITY_IDS_JSON_PROPERTY))) { + if (isSingleTextValue.test(mappingNode.get(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY)) && + isMultiValue.test(mappingNode.get(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_IDS_JSON_PROPERTY))) { mappingClass = ActivityMigrationMapping.OneToManyMapping.class; } - if (isMultiValue.test(mappingNode.get(FROM_ACTIVITY_IDS_JSON_PROPERTY)) && isSingleTextValue.test(mappingNode.get(TO_ACTIVITY_ID_JSON_PROPERTY))) { + if (isMultiValue.test(mappingNode.get(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_IDS_JSON_PROPERTY)) && + isSingleTextValue.test(mappingNode.get(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY))) { mappingClass = ActivityMigrationMapping.ManyToOneMapping.class; } @@ -234,8 +229,20 @@ public static ProcessInstanceMigrationDocument convertFromJson(String jsonProces documentBuilder.addActivityMigrationMapping(mapping); } } + + JsonNode enableActivityMappings = rootNode.get(ProcessInstanceMigrationDocumentConstants.ENABLE_ACTIVITY_MAPPINGS_JSON_SECTION); + if (enableActivityMappings != null) { + + for (JsonNode mappingNode : enableActivityMappings) { + if (mappingNode.hasNonNull(ProcessInstanceMigrationDocumentConstants.ACTIVITY_ID_JSON_PROPERTY)) { + EnableActivityMapping.EnableMapping enableMapping = new EnableActivityMapping.EnableMapping( + mappingNode.get(ProcessInstanceMigrationDocumentConstants.ACTIVITY_ID_JSON_PROPERTY).asText()); + documentBuilder.addEnableActivityMapping(enableMapping); + } + } + } - JsonNode processInstanceVariablesNode = rootNode.get(PROCESS_INSTANCE_VARIABLES_JSON_SECTION); + JsonNode processInstanceVariablesNode = rootNode.get(ProcessInstanceMigrationDocumentConstants.PROCESS_INSTANCE_VARIABLES_JSON_SECTION); if (processInstanceVariablesNode != null) { Map processInstanceVariables = ProcessInstanceMigrationDocumentConverter.convertFromJsonNodeToObject(processInstanceVariablesNode, objectMapper); documentBuilder.addProcessInstanceVariables(processInstanceVariables); @@ -270,12 +277,12 @@ public ObjectNode convertToJson(T mapping, ObjectMapper objectMapper) { JsonNode newAssigneeToJsonNode = convertNewAssigneeToJson(mapping, objectMapper); if (newAssigneeToJsonNode != null && !newAssigneeToJsonNode.isNull()) { - mappingNode.set(NEW_ASSIGNEE_JSON_PROPERTY, newAssigneeToJsonNode); + mappingNode.set(ProcessInstanceMigrationDocumentConstants.NEW_ASSIGNEE_JSON_PROPERTY, newAssigneeToJsonNode); } JsonNode variablesToJsonNode = convertLocalVariablesToJson(mapping, objectMapper); if (variablesToJsonNode != null && !variablesToJsonNode.isNull()) { - mappingNode.set(LOCAL_VARIABLES_JSON_SECTION, variablesToJsonNode); + mappingNode.set(ProcessInstanceMigrationDocumentConstants.LOCAL_VARIABLES_JSON_SECTION, variablesToJsonNode); } return mappingNode; @@ -286,11 +293,11 @@ public ObjectNode convertToJson(T mapping, ObjectMapper objectMapper) { protected ObjectNode convertAdditionalMappingInfoToJson(T mapping, ObjectMapper objectMapper) { ObjectNode mappingNode = objectMapper.createObjectNode(); if (mapping.isToParentProcess()) { - mappingNode.put(IN_PARENT_PROCESS_OF_CALL_ACTIVITY_JSON_PROPERTY, mapping.getFromCallActivityId()); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.IN_PARENT_PROCESS_OF_CALL_ACTIVITY_JSON_PROPERTY, mapping.getFromCallActivityId()); } if (mapping.isToCallActivity()) { - mappingNode.put(IN_SUB_PROCESS_OF_CALL_ACTIVITY_ID_JSON_PROPERTY, mapping.getToCallActivityId()); - mappingNode.put(CALL_ACTIVITY_PROCESS_DEFINITION_VERSION_JSON_PROPERTY, mapping.getCallActivityProcessDefinitionVersion()); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.IN_SUB_PROCESS_OF_CALL_ACTIVITY_ID_JSON_PROPERTY, mapping.getToCallActivityId()); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.CALL_ACTIVITY_PROCESS_DEFINITION_VERSION_JSON_PROPERTY, mapping.getCallActivityProcessDefinitionVersion()); } return mappingNode; } @@ -302,14 +309,14 @@ protected ObjectNode convertAdditionalMappingInfoToJson(T mapping, ObjectMapper public abstract T convertFromJson(JsonNode jsonNode, ObjectMapper objectMapper); protected > void convertAdditionalMappingInfoFromJson(M mapping, JsonNode jsonNode) { - Optional callActivityOfParentProcess = Optional.ofNullable(jsonNode.get(IN_PARENT_PROCESS_OF_CALL_ACTIVITY_JSON_PROPERTY)); + Optional callActivityOfParentProcess = Optional.ofNullable(jsonNode.get(ProcessInstanceMigrationDocumentConstants.IN_PARENT_PROCESS_OF_CALL_ACTIVITY_JSON_PROPERTY)); if (callActivityOfParentProcess.isPresent()) { callActivityOfParentProcess.map(JsonNode::textValue).ifPresent(mapping::inParentProcessOfCallActivityId); return; //if its a move to parent, it cannot be also a move to subProcess } - Optional ofCallActivityId = Optional.ofNullable(jsonNode.get(IN_SUB_PROCESS_OF_CALL_ACTIVITY_ID_JSON_PROPERTY)); - Optional subProcDefVer = Optional.ofNullable(jsonNode.get(CALL_ACTIVITY_PROCESS_DEFINITION_VERSION_JSON_PROPERTY)); + Optional ofCallActivityId = Optional.ofNullable(jsonNode.get(ProcessInstanceMigrationDocumentConstants.IN_SUB_PROCESS_OF_CALL_ACTIVITY_ID_JSON_PROPERTY)); + Optional subProcDefVer = Optional.ofNullable(jsonNode.get(ProcessInstanceMigrationDocumentConstants.CALL_ACTIVITY_PROCESS_DEFINITION_VERSION_JSON_PROPERTY)); if (ofCallActivityId.isPresent()) { if (subProcDefVer.isPresent()) { mapping.inSubProcessOfCallActivityId(ofCallActivityId.get().textValue(), subProcDefVer.get().intValue()); @@ -321,7 +328,7 @@ protected > void convertAdditionalM } protected V getLocalVariablesFromJson(JsonNode jsonNode, ObjectMapper objectMapper) { - JsonNode localVariablesNode = jsonNode.get(LOCAL_VARIABLES_JSON_SECTION); + JsonNode localVariablesNode = jsonNode.get(ProcessInstanceMigrationDocumentConstants.LOCAL_VARIABLES_JSON_SECTION); if (localVariablesNode != null) { return ProcessInstanceMigrationDocumentConverter.convertFromJsonNodeToObject(localVariablesNode, objectMapper); } @@ -329,8 +336,8 @@ protected V getLocalVariablesFromJson(JsonNode jsonNode, ObjectMapper object } protected String getNewAssigneeFromJson(JsonNode jsonNode) { - if (isSingleTextValue.test(jsonNode.get(NEW_ASSIGNEE_JSON_PROPERTY))) { - return jsonNode.get(NEW_ASSIGNEE_JSON_PROPERTY).textValue(); + if (isSingleTextValue.test(jsonNode.get(ProcessInstanceMigrationDocumentConstants.NEW_ASSIGNEE_JSON_PROPERTY))) { + return jsonNode.get(ProcessInstanceMigrationDocumentConstants.NEW_ASSIGNEE_JSON_PROPERTY).textValue(); } return null; } @@ -342,8 +349,8 @@ public static class OneToOneMappingConverter extends BaseActivityMigrationMappin @Override protected ObjectNode convertMappingInfoToJson(ActivityMigrationMapping.OneToOneMapping mapping, ObjectMapper objectMapper) { ObjectNode mappingNode = objectMapper.createObjectNode(); - mappingNode.put(FROM_ACTIVITY_ID_JSON_PROPERTY, mapping.getFromActivityId()); - mappingNode.put(TO_ACTIVITY_ID_JSON_PROPERTY, mapping.getToActivityId()); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY, mapping.getFromActivityId()); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY, mapping.getToActivityId()); mappingNode.setAll(convertAdditionalMappingInfoToJson(mapping, objectMapper)); return mappingNode; } @@ -364,8 +371,8 @@ protected JsonNode convertNewAssigneeToJson(ActivityMigrationMapping.OneToOneMap @Override public ActivityMigrationMapping.OneToOneMapping convertFromJson(JsonNode jsonNode, ObjectMapper objectMapper) { - String fromActivityId = jsonNode.get(FROM_ACTIVITY_ID_JSON_PROPERTY).textValue(); - String toActivityId = jsonNode.get(TO_ACTIVITY_ID_JSON_PROPERTY).textValue(); + String fromActivityId = jsonNode.get(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY).textValue(); + String toActivityId = jsonNode.get(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY).textValue(); ActivityMigrationMapping.OneToOneMapping oneToOneMapping = ActivityMigrationMapping.createMappingFor(fromActivityId, toActivityId); convertAdditionalMappingInfoFromJson(oneToOneMapping, jsonNode); @@ -389,8 +396,8 @@ public static class ManyToOneMappingConverter extends BaseActivityMigrationMappi protected ObjectNode convertMappingInfoToJson(ActivityMigrationMapping.ManyToOneMapping mapping, ObjectMapper objectMapper) { ObjectNode mappingNode = objectMapper.createObjectNode(); JsonNode fromActivityIdsNode = objectMapper.valueToTree(mapping.getFromActivityIds()); - mappingNode.set(FROM_ACTIVITY_IDS_JSON_PROPERTY, fromActivityIdsNode); - mappingNode.put(TO_ACTIVITY_ID_JSON_PROPERTY, mapping.getToActivityId()); + mappingNode.set(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_IDS_JSON_PROPERTY, fromActivityIdsNode); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY, mapping.getToActivityId()); mappingNode.setAll(convertAdditionalMappingInfoToJson(mapping, objectMapper)); return mappingNode; } @@ -411,11 +418,11 @@ protected JsonNode convertNewAssigneeToJson(ActivityMigrationMapping.ManyToOneMa @Override public ActivityMigrationMapping.ManyToOneMapping convertFromJson(JsonNode jsonNode, ObjectMapper objectMapper) { - JsonNode fromActivityIdsNode = jsonNode.get(FROM_ACTIVITY_IDS_JSON_PROPERTY); + JsonNode fromActivityIdsNode = jsonNode.get(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_IDS_JSON_PROPERTY); List fromActivityIds = objectMapper.convertValue(fromActivityIdsNode, new TypeReference<>() { }); - String toActivityId = jsonNode.get(TO_ACTIVITY_ID_JSON_PROPERTY).textValue(); + String toActivityId = jsonNode.get(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_ID_JSON_PROPERTY).textValue(); ActivityMigrationMapping.ManyToOneMapping manyToOneMapping = ActivityMigrationMapping.createMappingFor(fromActivityIds, toActivityId); convertAdditionalMappingInfoFromJson(manyToOneMapping, jsonNode); @@ -437,9 +444,9 @@ public static class OneToManyMappingConverter extends BaseActivityMigrationMappi @Override protected ObjectNode convertMappingInfoToJson(ActivityMigrationMapping.OneToManyMapping mapping, ObjectMapper objectMapper) { ObjectNode mappingNode = objectMapper.createObjectNode(); - mappingNode.put(FROM_ACTIVITY_ID_JSON_PROPERTY, mapping.getFromActivityId()); + mappingNode.put(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY, mapping.getFromActivityId()); JsonNode toActivityIdsNode = objectMapper.valueToTree(mapping.getToActivityIds()); - mappingNode.set(TO_ACTIVITY_IDS_JSON_PROPERTY, toActivityIdsNode); + mappingNode.set(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_IDS_JSON_PROPERTY, toActivityIdsNode); mappingNode.setAll(convertAdditionalMappingInfoToJson(mapping, objectMapper)); return mappingNode; } @@ -460,8 +467,8 @@ protected JsonNode convertNewAssigneeToJson(ActivityMigrationMapping.OneToManyMa @Override public ActivityMigrationMapping.OneToManyMapping convertFromJson(JsonNode jsonNode, ObjectMapper objectMapper) { - String fromActivityId = jsonNode.get(FROM_ACTIVITY_ID_JSON_PROPERTY).textValue(); - JsonNode toActivityIdsNode = jsonNode.get(TO_ACTIVITY_IDS_JSON_PROPERTY); + String fromActivityId = jsonNode.get(ProcessInstanceMigrationDocumentConstants.FROM_ACTIVITY_ID_JSON_PROPERTY).textValue(); + JsonNode toActivityIdsNode = jsonNode.get(ProcessInstanceMigrationDocumentConstants.TO_ACTIVITY_IDS_JSON_PROPERTY); List toActivityIds = objectMapper.convertValue(toActivityIdsNode, new TypeReference<>() { }); diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/runtime/ChangeActivityStateBuilder.java b/modules/flowable-engine/src/main/java/org/flowable/engine/runtime/ChangeActivityStateBuilder.java index 9565d6f65b2..37e8311b7ca 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/runtime/ChangeActivityStateBuilder.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/runtime/ChangeActivityStateBuilder.java @@ -81,6 +81,11 @@ public interface ChangeActivityStateBuilder { * Moves the execution with the current activity id to an activity id in a new sub process instance of the specific definition version for the provided call activity id. */ ChangeActivityStateBuilder moveActivityIdToSubProcessInstanceActivityId(String currentActivityId, String newActivityId, String callActivityId, Integer subProcessDefinitionVersion); + + /** + * Enables a new start event in an event sub process. + */ + ChangeActivityStateBuilder enableEventSubProcessStartEvent(String eventSubProcessStartEventId); /** * Sets a process scope variable diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/changestate/ChangeStateTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/changestate/ChangeStateTest.java index 2a5f1652f70..babdf8f6a65 100644 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/changestate/ChangeStateTest.java +++ b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/changestate/ChangeStateTest.java @@ -3397,5 +3397,36 @@ public void testSetCurrentExecutionToIntermediateCatchEventForMultipleProcessesT assertProcessEnded(processInstance2.getId()); } + @Test + @Deployment(resources = { "org/flowable/engine/test/api/runtime/changestate/multipleEventSubProcessEvents.bpmn20.xml" }) + public void testEnableEventSubProcessStartEvent() { + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("changeStateForEventSubProcess"); + + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + assertThat(task.getTaskDefinitionKey()).isEqualTo("processTask"); + + runtimeService.signalEventReceived("mySignal"); + + task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + assertThat(task.getTaskDefinitionKey()).isEqualTo("eventSubProcessTask"); + + assertThat(runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).count()).isEqualTo(0); + + runtimeService.createChangeActivityStateBuilder() + .processInstanceId(processInstance.getId()) + .enableEventSubProcessStartEvent("messageEventSubProcessStart") + .changeState(); + + assertThat(runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).count()).isEqualTo(1); + EventSubscription messageEventSubscription = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstance.getId()).singleResult(); + + runtimeService.messageEventReceived("myMessage", messageEventSubscription.getExecutionId()); + + task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + assertThat(task.getTaskDefinitionKey()).isEqualTo("messageEventSubProcessTask"); + taskService.complete(task.getId()); + + assertProcessEnded(processInstance.getId()); + } } diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationTest.java index 9cfc17ad194..621a0c341ab 100644 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationTest.java +++ b/modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationTest.java @@ -40,10 +40,13 @@ import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricDetail; import org.flowable.engine.history.HistoricProcessInstance; +import org.flowable.engine.impl.event.MessageEventHandler; +import org.flowable.engine.impl.event.SignalEventHandler; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.impl.persistence.entity.HistoricDetailVariableInstanceUpdateEntity; import org.flowable.engine.impl.test.HistoryTestHelper; import org.flowable.engine.migration.ActivityMigrationMapping; +import org.flowable.engine.migration.EnableActivityMapping; import org.flowable.engine.migration.ProcessInstanceMigrationBuilder; import org.flowable.engine.migration.ProcessInstanceMigrationDocument; import org.flowable.engine.migration.ProcessInstanceMigrationDocumentConverter; @@ -487,6 +490,472 @@ public void testMigrationWithNewSubProcessScope() { assertProcessEnded(processInstanceToMigrate.getId()); } + + @Test + public void testMigrationWithNewEventSubProcess() { + //Deploy first version of the process + deployProcessDefinition("my deploy", "org/flowable/engine/test/api/runtime/migration/two-tasks-simple-process.bpmn20.xml"); + + //Start and instance of the recent first version of the process for migration and one for reference + ProcessInstance processInstanceToMigrate = runtimeService.startProcessInstanceByKey("MP"); + taskService.complete(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult().getId()); + + Task task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + + //Deploy second version of the process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/two-tasks-with-event-subprocess.bpmn20.xml"); + + //Migrate process + processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("eventSubProcessStart")) + .migrate(processInstanceToMigrate.getId()); + + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(executions).hasSize(3); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + assertThat(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(1); + + EventSubscription eventSubscription = runtimeService.createEventSubscriptionQuery().activityId("eventSubProcessStart").singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + if (HistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, processEngineConfiguration)) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicTaskInstances).hasSize(2); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + List historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicActivityInstances).hasSize(5); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + } + + // complete final task + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate.getId()); + } + + @Test + public void testMigrationAndTriggerNewEventSubProcess() { + //Deploy first version of the process + deployProcessDefinition("my deploy", "org/flowable/engine/test/api/runtime/migration/two-tasks-simple-process.bpmn20.xml"); + + //Start and instance of the recent first version of the process for migration and one for reference + ProcessInstance processInstanceToMigrate = runtimeService.startProcessInstanceByKey("MP"); + taskService.complete(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult().getId()); + + Task task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + + //Deploy second version of the process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/two-tasks-with-event-subprocess.bpmn20.xml"); + + //Migrate process + processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("eventSubProcessStart")) + .migrate(processInstanceToMigrate.getId()); + + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(executions).hasSize(3); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + EventSubscription eventSubscription = runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("eventSubProcessStart") + .singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + runtimeService.signalEventReceived("mySignal"); + + assertThat(runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("eventSubProcessStart").count()).isEqualTo(1); + + assertThat(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(2); + + if (HistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, processEngineConfiguration)) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicTaskInstances).hasSize(3); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + List historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicActivityInstances).hasSize(9); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + } + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).taskDefinitionKey("eventSubProcessTask").singleResult(); + taskService.complete(task.getId()); + + // complete final task + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate.getId()); + } + + @Test + public void testMigrationAndTriggerInterruptingNewEventSubProcess() { + //Deploy first version of the process + deployProcessDefinition("my deploy", "org/flowable/engine/test/api/runtime/migration/two-tasks-simple-process.bpmn20.xml"); + + //Start and instance of the recent first version of the process for migration and one for reference + ProcessInstance processInstanceToMigrate = runtimeService.startProcessInstanceByKey("MP"); + taskService.complete(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult().getId()); + + Task task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + + //Deploy second version of the process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/two-tasks-with-interrupting-event-subprocess.bpmn20.xml"); + + //Migrate process + processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("eventSubProcessStart")) + .migrate(processInstanceToMigrate.getId()); + + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(executions).hasSize(3); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + EventSubscription eventSubscription = runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("eventSubProcessStart") + .singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + runtimeService.signalEventReceived("mySignal"); + + assertThat(runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("eventSubProcessStart").count()).isEqualTo(0); + + assertThat(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(1); + + if (HistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, processEngineConfiguration)) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicTaskInstances).hasSize(3); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + List historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicActivityInstances).hasSize(9); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + } + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).taskDefinitionKey("eventSubProcessTask").singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate.getId()); + } + + @Test + public void testMigrationWithMultipleNewEventSubProcess() { + //Deploy first version of the process + deployProcessDefinition("my deploy", "org/flowable/engine/test/api/runtime/migration/two-tasks-simple-process.bpmn20.xml"); + + //Start and instance of the recent first version of the process for migration and one for reference + ProcessInstance processInstanceToMigrate = runtimeService.startProcessInstanceByKey("MP"); + taskService.complete(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult().getId()); + + Task task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + + //Deploy second version of the process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-event-subprocess-events.bpmn20.xml"); + + //Migrate process + processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("eventSubProcessStart")) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("messageEventSubProcessStart")) + .migrate(processInstanceToMigrate.getId()); + + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(executions).hasSize(4); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + EventSubscription eventSubscription = runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("eventSubProcessStart") + .singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + eventSubscription = runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("messageEventSubProcessStart") + .singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(MessageEventHandler.EVENT_HANDLER_TYPE); + + runtimeService.signalEventReceived("mySignal"); + + assertThat(runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(2); + + assertThat(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(2); + + if (HistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, processEngineConfiguration)) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicTaskInstances).hasSize(3); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + List historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicActivityInstances).hasSize(9); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + } + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).taskDefinitionKey("eventSubProcessTask").singleResult(); + taskService.complete(task.getId()); + + // complete final task + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate.getId()); + } + + @Test + public void testMigrationWithInterruptingMultipleNewEventSubProcess() { + //Deploy first version of the process + deployProcessDefinition("my deploy", "org/flowable/engine/test/api/runtime/migration/two-tasks-simple-process.bpmn20.xml"); + + //Start and instance of the recent first version of the process for migration and one for reference + ProcessInstance processInstanceToMigrate = runtimeService.startProcessInstanceByKey("MP"); + taskService.complete(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult().getId()); + + Task task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).singleResult(); + + //Deploy second version of the process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-interrupting-event-subprocess-events.bpmn20.xml"); + + //Migrate process + processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("eventSubProcessStart")) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("messageEventSubProcessStart")) + .migrate(processInstanceToMigrate.getId()); + + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(executions).hasSize(4); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + EventSubscription eventSubscription = runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("eventSubProcessStart") + .singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + eventSubscription = runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()) + .activityId("messageEventSubProcessStart") + .singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(MessageEventHandler.EVENT_HANDLER_TYPE); + + runtimeService.signalEventReceived("mySignal"); + + assertThat(runtimeService.createEventSubscriptionQuery() + .processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(0); + + assertThat(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).count()).isEqualTo(1); + + if (HistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, processEngineConfiguration)) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicTaskInstances).hasSize(3); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + List historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate.getId()).list(); + assertThat(historicActivityInstances).hasSize(9); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + } + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate.getId()).taskDefinitionKey("eventSubProcessTask").singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate.getId()); + } + + @Test + public void testDefinitionMigrationWithNewEventSubProcess() { + //Deploy first version of the process + deployProcessDefinition("my deploy", "org/flowable/engine/test/api/runtime/migration/two-tasks-simple-process.bpmn20.xml"); + + ProcessInstance processInstanceToMigrate1 = runtimeService.startProcessInstanceByKey("MP"); + taskService.complete(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate1.getId()).singleResult().getId()); + + Task task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate1.getId()).singleResult(); + + ProcessInstance processInstanceToMigrate2 = runtimeService.startProcessInstanceByKey("MP"); + + //Deploy second version of the process + ProcessDefinition version2ProcessDef = deployProcessDefinition("my deploy", + "org/flowable/engine/test/api/runtime/migration/two-tasks-with-event-subprocess.bpmn20.xml"); + + //Migrate process + processMigrationService.createProcessInstanceMigrationBuilder() + .migrateToProcessDefinition(version2ProcessDef.getId()) + .addEnableEventSubProcessStartEvent( + EnableActivityMapping.enable("eventSubProcessStart")) + .migrateProcessInstances(processInstanceToMigrate1.getProcessDefinitionId()); + + List executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate1.getId()).list(); + assertThat(executions).hasSize(3); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceToMigrate2.getId()).list(); + assertThat(executions).hasSize(3); //includes root execution + for (Execution execution : executions) { + assertThat(((ExecutionEntity) execution).getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + assertThat(taskService.createTaskQuery().processInstanceId(processInstanceToMigrate1.getId()).count()).isEqualTo(1); + + EventSubscription eventSubscription = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstanceToMigrate1.getId()).activityId("eventSubProcessStart").singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + eventSubscription = runtimeService.createEventSubscriptionQuery().processInstanceId(processInstanceToMigrate2.getId()).activityId("eventSubProcessStart").singleResult(); + assertThat(eventSubscription).isNotNull(); + assertThat(eventSubscription.getEventType()).isEqualTo(SignalEventHandler.EVENT_HANDLER_TYPE); + + runtimeService.signalEventReceived("mySignal"); + + if (HistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, processEngineConfiguration)) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate1.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate1.getId()).list(); + assertThat(historicTaskInstances).hasSize(3); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + List historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate1.getId()).list(); + assertThat(historicActivityInstances).hasSize(9); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + historicProcessInstance = historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstanceToMigrate2.getId()).singleResult(); + assertThat(historicProcessInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + + historicTaskInstances = historyService.createHistoricTaskInstanceQuery() + .processInstanceId(processInstanceToMigrate2.getId()).list(); + assertThat(historicTaskInstances).hasSize(2); + for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) { + assertThat(historicTaskInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + + historicActivityInstances = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceToMigrate2.getId()).list(); + assertThat(historicActivityInstances).hasSize(7); + for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { + assertThat(historicActivityInstance.getProcessDefinitionId()).isEqualTo(version2ProcessDef.getId()); + } + } + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate1.getId()).taskDefinitionKey("userTask2Id").singleResult(); + taskService.complete(task.getId()); + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate1.getId()).taskDefinitionKey("eventSubProcessTask").singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate1.getId()); + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate2.getId()).taskDefinitionKey("userTask1Id").singleResult(); + taskService.complete(task.getId()); + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate2.getId()).taskDefinitionKey("userTask2Id").singleResult(); + taskService.complete(task.getId()); + + task = taskService.createTaskQuery().processInstanceId(processInstanceToMigrate2.getId()).taskDefinitionKey("eventSubProcessTask").singleResult(); + taskService.complete(task.getId()); + + assertProcessEnded(processInstanceToMigrate2.getId()); + } @Test public void testSimpleMigrationOfProcessInstancesById() { diff --git a/modules/flowable-engine/src/test/java/org/flowable/engine/test/jobexecutor/JobExecutorTest.java b/modules/flowable-engine/src/test/java/org/flowable/engine/test/jobexecutor/JobExecutorTest.java deleted file mode 100644 index 99fe1953df3..00000000000 --- a/modules/flowable-engine/src/test/java/org/flowable/engine/test/jobexecutor/JobExecutorTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* 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.flowable.engine.test.jobexecutor; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashSet; -import java.util.Set; -import java.util.TreeSet; - -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.common.engine.impl.interceptor.CommandExecutor; -import org.flowable.common.engine.impl.interceptor.EngineConfigurationConstants; -import org.flowable.job.service.JobServiceConfiguration; -import org.flowable.job.service.impl.asyncexecutor.JobManager; -import org.flowable.job.service.impl.persistence.entity.TimerJobEntityManager; -import org.junit.jupiter.api.Test; - -/** - * @author Tom Baeyens - */ -public class JobExecutorTest extends JobExecutorTestCase { - - @Test - public void testBasicJobExecutorOperation() throws Exception { - CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); - commandExecutor.execute(new Command() { - @Override - public Void execute(CommandContext commandContext) { - JobServiceConfiguration jobServiceConfiguration = (JobServiceConfiguration) processEngineConfiguration.getServiceConfigurations().get(EngineConfigurationConstants.KEY_JOB_SERVICE_CONFIG); - JobManager jobManager = jobServiceConfiguration.getJobManager(); - jobManager.execute(createTweetMessage("message-one")); - jobManager.execute(createTweetMessage("message-two")); - jobManager.execute(createTweetMessage("message-three")); - jobManager.execute(createTweetMessage("message-four")); - - TimerJobEntityManager timerJobManager = jobServiceConfiguration.getTimerJobEntityManager(); - timerJobManager.insert(createTweetTimer("timer-one", new Date())); - timerJobManager.insert(createTweetTimer("timer-one", new Date())); - timerJobManager.insert(createTweetTimer("timer-two", new Date())); - return null; - } - }); - - GregorianCalendar currentCal = new GregorianCalendar(); - currentCal.add(Calendar.MINUTE, 1); - processEngineConfiguration.getClock().setCurrentTime(currentCal.getTime()); - - waitForJobExecutorToProcessAllJobsAndExecutableTimerJobs(12500L, 200L); - - Set messages = new HashSet<>(tweetHandler.getMessages()); - Set expectedMessages = new HashSet<>(); - expectedMessages.add("message-one"); - expectedMessages.add("message-two"); - expectedMessages.add("message-three"); - expectedMessages.add("message-four"); - expectedMessages.add("timer-one"); - expectedMessages.add("timer-two"); - - assertThat(new TreeSet<>(messages)).isEqualTo(new TreeSet<>(expectedMessages)); - } -} diff --git a/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/changestate/multipleEventSubProcessEvents.bpmn20.xml b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/changestate/multipleEventSubProcessEvents.bpmn20.xml new file mode 100644 index 00000000000..dc7b0e83748 --- /dev/null +++ b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/changestate/multipleEventSubProcessEvents.bpmn20.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-event-subprocess.bpmn20.xml b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-event-subprocess.bpmn20.xml new file mode 100644 index 00000000000..93b0b94778f --- /dev/null +++ b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-event-subprocess.bpmn20.xml @@ -0,0 +1,27 @@ + + + + + My process documentation + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-interrupting-event-subprocess.bpmn20.xml b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-interrupting-event-subprocess.bpmn20.xml new file mode 100644 index 00000000000..2f6571f83f4 --- /dev/null +++ b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-interrupting-event-subprocess.bpmn20.xml @@ -0,0 +1,27 @@ + + + + + My process documentation + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-event-subprocess-events.bpmn20.xml b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-event-subprocess-events.bpmn20.xml new file mode 100644 index 00000000000..7005fe02f6c --- /dev/null +++ b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-event-subprocess-events.bpmn20.xml @@ -0,0 +1,36 @@ + + + + + + My process documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-interrupting-event-subprocess-events.bpmn20.xml b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-interrupting-event-subprocess-events.bpmn20.xml new file mode 100644 index 00000000000..7456b292e3d --- /dev/null +++ b/modules/flowable-engine/src/test/resources/org/flowable/engine/test/api/runtime/migration/two-tasks-with-multiple-interrupting-event-subprocess-events.bpmn20.xml @@ -0,0 +1,36 @@ + + + + + + My process documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file