From 9c97e3f47aac8a172ef132f550cfc12582250742 Mon Sep 17 00:00:00 2001 From: BertMatthys Date: Mon, 16 Mar 2026 12:58:57 +0100 Subject: [PATCH 1/2] Stop the creation of historic entity links when the child process/case instance has history level NONE --- .../impl/cmmn/DefaultCaseInstanceService.java | 36 ++-- .../DefaultProcessInstanceService.java | 43 ++-- .../cmmn/test/EntityLinkHistoryLevelTest.java | 199 ++++++++++++++++++ ...ActivityProcessHistoryNoneChild.bpmn20.xml | 14 ++ ...evelTest.caseTaskCaseHistoryNoneChild.cmmn | 26 +++ ...caseTaskProcessHistoryNoneChild.bpmn20.xml | 14 ++ ...LevelTest.oneHumanTaskCaseHistoryNone.cmmn | 16 ++ ...lTest.oneTaskProcessHistoryNone.bpmn20.xml | 15 ++ ...lTest.processTaskCaseHistoryNoneChild.cmmn | 28 +++ .../impl/ProcessTaskActivityBehavior.java | 17 +- ...faultCmmnHistoryConfigurationSettings.java | 18 +- .../impl/process/ProcessInstanceService.java | 23 +- .../impl/runtime/CaseInstanceHelper.java | 4 + .../impl/runtime/CaseInstanceHelperImpl.java | 96 +++++---- .../cmmn/engine/impl/util/EntityLinkUtil.java | 31 ++- .../behavior/CaseTaskActivityBehavior.java | 21 +- .../impl/cmd/StartProcessInstanceCmd.java | 60 +----- .../engine/impl/cmmn/CaseInstanceService.java | 23 +- .../DefaultHistoryConfigurationSettings.java | 18 +- .../engine/impl/util/EntityLinkUtil.java | 34 ++- .../impl/util/ProcessInstanceHelper.java | 56 +++++ 21 files changed, 624 insertions(+), 168 deletions(-) create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/java/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.java create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.callActivityProcessHistoryNoneChild.bpmn20.xml create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskCaseHistoryNoneChild.cmmn create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskProcessHistoryNoneChild.bpmn20.xml create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneHumanTaskCaseHistoryNone.cmmn create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneTaskProcessHistoryNone.bpmn20.xml create mode 100644 modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.processTaskCaseHistoryNoneChild.cmmn diff --git a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java index 1f550ccd639..a93e875a626 100644 --- a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java +++ b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java @@ -18,6 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.flowable.cmmn.api.CallbackTypes; import org.flowable.cmmn.api.CmmnRuntimeService; +import org.flowable.cmmn.api.repository.CaseDefinition; import org.flowable.cmmn.api.runtime.CaseInstance; import org.flowable.cmmn.api.runtime.CaseInstanceBuilder; import org.flowable.cmmn.api.runtime.CaseInstanceState; @@ -51,21 +52,16 @@ public String generateNewCaseInstanceId() { } @Override - public String startCaseInstanceByKey(String caseDefinitionKey, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, - String executionId, - String tenantId, boolean fallbackToDefaultTenant, String parentDeploymentId, Map inParametersMap) { - + public String startCaseInstanceByKey(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, + String executionId, String tenantId, Map inParametersMap) { + CaseInstanceBuilder caseInstanceBuilder = cmmnEngineConfiguration.getCmmnRuntimeService().createCaseInstanceBuilder(); - caseInstanceBuilder.caseDefinitionKey(caseDefinitionKey); + caseInstanceBuilder.caseDefinitionId(caseDefinitionId); - if (parentDeploymentId != null) { - caseInstanceBuilder.caseDefinitionParentDeploymentId(parentDeploymentId); - } - if (predefinedCaseInstanceId != null) { caseInstanceBuilder.predefinedCaseInstanceId(predefinedCaseInstanceId); } - + if (tenantId != null) { caseInstanceBuilder.tenantId(tenantId); caseInstanceBuilder.overrideCaseDefinitionTenantId(tenantId); @@ -80,10 +76,6 @@ public String startCaseInstanceByKey(String caseDefinitionKey, String predefined caseInstanceBuilder.variable(target, inParametersMap.get(target)); } - if (fallbackToDefaultTenant) { - caseInstanceBuilder.fallbackToDefaultTenant(); - } - if (businessKey != null) { caseInstanceBuilder.businessKey(businessKey); } @@ -91,7 +83,7 @@ public String startCaseInstanceByKey(String caseDefinitionKey, String predefined if (caseInstanceName != null) { caseInstanceBuilder.name(caseInstanceName); } - + CaseInstance caseInstance = caseInstanceBuilder.start(); return caseInstance.getId(); } @@ -142,6 +134,20 @@ public void deleteCaseInstancesForExecutionId(String executionId) { } } + @Override + public String resolveCaseDefinitionId(String caseDefinitionKey, String tenantId, + boolean fallbackToDefaultTenant, String parentDeploymentId) { + CaseDefinition caseDefinition = cmmnEngineConfiguration.getCaseInstanceHelper() + .resolveCaseDefinition(caseDefinitionKey, tenantId, + fallbackToDefaultTenant || cmmnEngineConfiguration.isFallbackToDefaultTenant(), parentDeploymentId); + return caseDefinition.getId(); + } + + @Override + public boolean isHistoryEnabledForCaseDefinitionId(String caseDefinitionId) { + return cmmnEngineConfiguration.getCmmnHistoryConfigurationSettings().isHistoryEnabled(caseDefinitionId); + } + @Override public void deleteCaseInstanceWithoutAgenda(String caseInstanceId) { cmmnEngineConfiguration.getCommandExecutor().execute(commandContext -> { diff --git a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java index d7738ae1d21..b4ebe42831e 100644 --- a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java +++ b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java @@ -29,6 +29,7 @@ import org.flowable.engine.impl.persistence.entity.BpmnEngineEntityConstants; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstanceBuilder; import org.flowable.form.api.FormInfo; @@ -56,30 +57,27 @@ public String generateNewProcessInstanceId() { } @Override - public String startProcessInstanceByKey(String processDefinitionKey, String predefinedProcessInstanceId, String stageInstanceId, - String tenantId, Boolean fallbackToDefaultTenant, String parentDeploymentId, Map inParametersMap, String businessKey, + public String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId, + String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome) { - - return startProcessInstanceByKey(processDefinitionKey, predefinedProcessInstanceId, null, stageInstanceId, tenantId, fallbackToDefaultTenant, - parentDeploymentId, inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); + + return startProcessInstanceByKey(processDefinitionId, predefinedProcessInstanceId, null, stageInstanceId, tenantId, + inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); } @Override - public String startProcessInstanceByKey(String processDefinitionKey, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, - String tenantId, Boolean fallbackToDefaultTenant, String parentDeploymentId, Map inParametersMap, String businessKey, + public String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, + String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome) { - + ProcessInstanceBuilder processInstanceBuilder = processEngineConfiguration.getRuntimeService().createProcessInstanceBuilder(); - processInstanceBuilder.processDefinitionKey(processDefinitionKey); + processInstanceBuilder.processDefinitionId(processDefinitionId); + if (tenantId != null) { processInstanceBuilder.tenantId(tenantId); processInstanceBuilder.overrideProcessDefinitionTenantId(tenantId); } - if (parentDeploymentId != null) { - processInstanceBuilder.processDefinitionParentDeploymentId(parentDeploymentId); - } - processInstanceBuilder.predefineProcessInstanceId(predefinedProcessInstanceId); if (planItemInstanceId != null) { @@ -91,10 +89,6 @@ public String startProcessInstanceByKey(String processDefinitionKey, String pred processInstanceBuilder.variable(target, inParametersMap.get(target)); } - if (fallbackToDefaultTenant != null && fallbackToDefaultTenant) { - processInstanceBuilder.fallbackToDefaultTenant(); - } - if (businessKey != null) { processInstanceBuilder.businessKey(businessKey); } @@ -146,6 +140,21 @@ public List getOutputParametersOfCaseTask(String executionId) { return cmmnParameters; } + @Override + public String resolveProcessDefinitionId(String processDefinitionKey, String tenantId, + Boolean fallbackToDefaultTenant, String parentDeploymentId) { + ProcessDefinition processDefinition = processEngineConfiguration.getProcessInstanceHelper() + .resolveProcessDefinition(processDefinitionKey, tenantId, + Boolean.TRUE.equals(fallbackToDefaultTenant) || processEngineConfiguration.isFallbackToDefaultTenant(), + parentDeploymentId, processEngineConfiguration); + return processDefinition.getId(); + } + + @Override + public boolean isHistoryEnabledForProcessDefinitionId(String processDefinitionId) { + return processEngineConfiguration.getHistoryConfigurationSettings().isHistoryEnabled(processDefinitionId); + } + @Override public void deleteProcessInstance(String processInstanceId) { processEngineConfiguration.getCommandExecutor().execute(commandContext -> { diff --git a/modules/flowable-cmmn-engine-configurator/src/test/java/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.java b/modules/flowable-cmmn-engine-configurator/src/test/java/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.java new file mode 100644 index 00000000000..0632ed8cb82 --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/java/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.java @@ -0,0 +1,199 @@ +/* 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.cmmn.test; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.flowable.cmmn.api.repository.CmmnDeployment; +import org.flowable.cmmn.api.runtime.CaseInstance; +import org.flowable.common.engine.api.scope.ScopeTypes; +import org.flowable.engine.repository.Deployment; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.entitylink.api.EntityLink; +import org.flowable.entitylink.api.history.HistoricEntityLink; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Tests that historic entity links are not created when the child sub-instance has history level NONE, + * even when the parent has history enabled. + */ +public class EntityLinkHistoryLevelTest extends AbstractProcessEngineIntegrationTest { + + @BeforeEach + public void enableDefinitionHistoryLevel() { + processEngineConfiguration.setEnableProcessDefinitionHistoryLevel(true); + cmmnEngineConfiguration.setEnableCaseDefinitionHistoryLevel(true); + } + + @AfterEach + public void disableDefinitionHistoryLevel() { + processEngineConfiguration.setEnableProcessDefinitionHistoryLevel(false); + cmmnEngineConfiguration.setEnableCaseDefinitionHistoryLevel(false); + } + + @Test + public void testBpmnParentWithCmmnChildHistoryNone() { + CmmnDeployment cmmnDeployment = cmmnRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneHumanTaskCaseHistoryNone.cmmn") + .deploy(); + Deployment bpmnDeployment = processEngineRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskProcessHistoryNoneChild.bpmn20.xml") + .deploy(); + + try { + ProcessInstance processInstance = processEngineRuntimeService.startProcessInstanceByKey("caseTaskHistoryNoneChild"); + + // The case task should have started a child case instance + CaseInstance childCaseInstance = cmmnRuntimeService.createCaseInstanceQuery().singleResult(); + assertThat(childCaseInstance).isNotNull(); + + // Runtime entity links should exist (parent process -> child case) + List entityLinks = processEngineRuntimeService.getEntityLinkChildrenForProcessInstance(processInstance.getId()); + assertThat(entityLinks).isNotEmpty(); + assertThat(entityLinks) + .anyMatch(el -> ScopeTypes.CMMN.equals(el.getReferenceScopeType()) + && childCaseInstance.getId().equals(el.getReferenceScopeId())); + + // Historic entity link to the child CMMN case should NOT exist because the child case has historyLevel=none + List historicEntityLinks = processEngineHistoryService + .getHistoricEntityLinkChildrenForProcessInstance(processInstance.getId()); + assertThat(historicEntityLinks) + .noneMatch(el -> ScopeTypes.CMMN.equals(el.getReferenceScopeType()) + && childCaseInstance.getId().equals(el.getReferenceScopeId())); + + } finally { + cmmnRepositoryService.deleteDeployment(cmmnDeployment.getId(), true); + processEngineRepositoryService.deleteDeployment(bpmnDeployment.getId(), true); + } + } + + @Test + public void testCmmnParentWithBpmnChildHistoryNone() { + CmmnDeployment cmmnDeployment = cmmnRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.processTaskCaseHistoryNoneChild.cmmn") + .deploy(); + Deployment bpmnDeployment = processEngineRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneTaskProcessHistoryNone.bpmn20.xml") + .deploy(); + + try { + CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder() + .caseDefinitionKey("processTaskCase") + .start(); + + // The process task should have started a child process instance + ProcessInstance childProcessInstance = processEngineRuntimeService.createProcessInstanceQuery().singleResult(); + assertThat(childProcessInstance).isNotNull(); + + // Runtime entity links should exist (parent case -> child process) + List entityLinks = cmmnRuntimeService.getEntityLinkChildrenForCaseInstance(caseInstance.getId()); + assertThat(entityLinks).isNotEmpty(); + assertThat(entityLinks) + .anyMatch(el -> ScopeTypes.BPMN.equals(el.getReferenceScopeType()) + && childProcessInstance.getId().equals(el.getReferenceScopeId())); + + // Historic entity link to the child BPMN process should NOT exist because the child process has historyLevel=none + List historicEntityLinks = cmmnHistoryService + .getHistoricEntityLinkChildrenForCaseInstance(caseInstance.getId()); + assertThat(historicEntityLinks) + .noneMatch(el -> ScopeTypes.BPMN.equals(el.getReferenceScopeType()) + && childProcessInstance.getId().equals(el.getReferenceScopeId())); + + } finally { + cmmnRepositoryService.deleteDeployment(cmmnDeployment.getId(), true); + processEngineRepositoryService.deleteDeployment(bpmnDeployment.getId(), true); + } + } + + @Test + public void testBpmnParentWithBpmnChildHistoryNone() { + Deployment childDeployment = processEngineRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneTaskProcessHistoryNone.bpmn20.xml") + .deploy(); + Deployment parentDeployment = processEngineRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.callActivityProcessHistoryNoneChild.bpmn20.xml") + .deploy(); + + try { + ProcessInstance processInstance = processEngineRuntimeService.startProcessInstanceByKey("callActivityHistoryNoneChild"); + + // The call activity should have started a child process instance + ProcessInstance childProcessInstance = processEngineRuntimeService.createProcessInstanceQuery() + .superProcessInstanceId(processInstance.getId()) + .singleResult(); + assertThat(childProcessInstance).isNotNull(); + + // Runtime entity links should exist (parent process -> child process) + List entityLinks = processEngineRuntimeService.getEntityLinkChildrenForProcessInstance(processInstance.getId()); + assertThat(entityLinks).isNotEmpty(); + assertThat(entityLinks) + .anyMatch(el -> ScopeTypes.BPMN.equals(el.getReferenceScopeType()) + && childProcessInstance.getId().equals(el.getReferenceScopeId())); + + // Historic entity link to the child BPMN process should NOT exist because the child process has historyLevel=none + List historicEntityLinks = processEngineHistoryService + .getHistoricEntityLinkChildrenForProcessInstance(processInstance.getId()); + assertThat(historicEntityLinks) + .noneMatch(el -> ScopeTypes.BPMN.equals(el.getReferenceScopeType()) + && childProcessInstance.getId().equals(el.getReferenceScopeId())); + + } finally { + processEngineRepositoryService.deleteDeployment(parentDeployment.getId(), true); + processEngineRepositoryService.deleteDeployment(childDeployment.getId(), true); + } + } + + @Test + public void testCmmnParentWithCmmnChildHistoryNone() { + CmmnDeployment childDeployment = cmmnRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneHumanTaskCaseHistoryNone.cmmn") + .deploy(); + CmmnDeployment parentDeployment = cmmnRepositoryService.createDeployment() + .addClasspathResource("org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskCaseHistoryNoneChild.cmmn") + .deploy(); + + try { + CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder() + .caseDefinitionKey("caseTaskCaseHistoryNoneChild") + .start(); + + // The case task should have started a child case instance + CaseInstance childCaseInstance = cmmnRuntimeService.createCaseInstanceQuery() + .caseInstanceParentId(caseInstance.getId()) + .singleResult(); + assertThat(childCaseInstance).isNotNull(); + + // Runtime entity links should exist (parent case -> child case) + List entityLinks = cmmnRuntimeService.getEntityLinkChildrenForCaseInstance(caseInstance.getId()); + assertThat(entityLinks).isNotEmpty(); + assertThat(entityLinks) + .anyMatch(el -> ScopeTypes.CMMN.equals(el.getReferenceScopeType()) + && childCaseInstance.getId().equals(el.getReferenceScopeId())); + + // Historic entity link to the child CMMN case should NOT exist because the child case has historyLevel=none + List historicEntityLinks = cmmnHistoryService + .getHistoricEntityLinkChildrenForCaseInstance(caseInstance.getId()); + assertThat(historicEntityLinks) + .noneMatch(el -> ScopeTypes.CMMN.equals(el.getReferenceScopeType()) + && childCaseInstance.getId().equals(el.getReferenceScopeId())); + + } finally { + cmmnRepositoryService.deleteDeployment(parentDeployment.getId(), true); + cmmnRepositoryService.deleteDeployment(childDeployment.getId(), true); + } + } +} diff --git a/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.callActivityProcessHistoryNoneChild.bpmn20.xml b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.callActivityProcessHistoryNoneChild.bpmn20.xml new file mode 100644 index 00000000000..f1481230a0b --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.callActivityProcessHistoryNoneChild.bpmn20.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskCaseHistoryNoneChild.cmmn b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskCaseHistoryNoneChild.cmmn new file mode 100644 index 00000000000..62373ea3f22 --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskCaseHistoryNoneChild.cmmn @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + complete + + + + + + + + + + diff --git a/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskProcessHistoryNoneChild.bpmn20.xml b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskProcessHistoryNoneChild.bpmn20.xml new file mode 100644 index 00000000000..c08c3649c5b --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.caseTaskProcessHistoryNoneChild.bpmn20.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneHumanTaskCaseHistoryNone.cmmn b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneHumanTaskCaseHistoryNone.cmmn new file mode 100644 index 00000000000..f64650e14dc --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneHumanTaskCaseHistoryNone.cmmn @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneTaskProcessHistoryNone.bpmn20.xml b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneTaskProcessHistoryNone.bpmn20.xml new file mode 100644 index 00000000000..6f70c6904c8 --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.oneTaskProcessHistoryNone.bpmn20.xml @@ -0,0 +1,15 @@ + + + + + none + + + + + + + + diff --git a/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.processTaskCaseHistoryNoneChild.cmmn b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.processTaskCaseHistoryNoneChild.cmmn new file mode 100644 index 00000000000..fe53701b5ff --- /dev/null +++ b/modules/flowable-cmmn-engine-configurator/src/test/resources/org/flowable/cmmn/test/EntityLinkHistoryLevelTest.processTaskCaseHistoryNoneChild.cmmn @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + complete + + + + + + + + + + + + diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java index 5ce978a3670..59c890aab64 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java @@ -118,18 +118,25 @@ public void execute(CommandContext commandContext, PlanItemInstanceEntity planIt String parentDeploymentId = getParentDeploymentIfSameDeployment(cmmnEngineConfiguration, planItemInstanceEntity); + // Resolve the process definition already so we can check its history level for entity links + String processDefinitionId = processInstanceService.resolveProcessDefinitionId(externalRef, + planItemInstanceEntity.getTenantId(), fallbackToDefaultTenant, parentDeploymentId); + if (blocking) { if (CommandContextUtil.getCmmnEngineConfiguration(commandContext).isEnableEntityLinks()) { + boolean createHistoricEntityLinks = processInstanceService.isHistoryEnabledForProcessDefinitionId(processDefinitionId); + EntityLinkUtil.createEntityLinks(planItemInstanceEntity.getCaseInstanceId(), planItemInstanceEntity.getId(), - planItemInstanceEntity.getPlanItemDefinitionId(), processInstanceId, ScopeTypes.BPMN, cmmnEngineConfiguration); + planItemInstanceEntity.getPlanItemDefinitionId(), processInstanceId, ScopeTypes.BPMN, cmmnEngineConfiguration, createHistoricEntityLinks); } - processInstanceService.startProcessInstanceByKey(externalRef, processInstanceId, planItemInstanceEntity.getId(), planItemInstanceEntity.getStageInstanceId(), - planItemInstanceEntity.getTenantId(), fallbackToDefaultTenant, parentDeploymentId, inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); + processInstanceService.startProcessInstanceByKey(processDefinitionId, processInstanceId, planItemInstanceEntity.getId(), planItemInstanceEntity.getStageInstanceId(), + planItemInstanceEntity.getTenantId(), inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); + } else { - processInstanceService.startProcessInstanceByKey(externalRef, processInstanceId, planItemInstanceEntity.getStageInstanceId(), - planItemInstanceEntity.getTenantId(), fallbackToDefaultTenant, parentDeploymentId, inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); + processInstanceService.startProcessInstanceByKey(processDefinitionId, processInstanceId, planItemInstanceEntity.getStageInstanceId(), + planItemInstanceEntity.getTenantId(), inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); } if (!blocking) { diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java index f5198db6bb9..1ba89e267d0 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java @@ -245,8 +245,24 @@ protected String getCaseDefinitionId(IdentityLinkEntity identityLink) { @Override public boolean isHistoryEnabledForEntityLink(EntityLinkEntity entityLink) { + // Check if history is enabled for the source scope String caseDefinitionId = getCaseDefinitionId(entityLink); - return isHistoryEnabled(caseDefinitionId); + if (!isHistoryEnabled(caseDefinitionId)) { + return false; + } + + // Also check the history level of the reference scope (if it is NONE we should not create the entity link) + String referenceScopeId = entityLink.getReferenceScopeId(); + String referenceScopeType = entityLink.getReferenceScopeType(); + // Check that the scope type is CMMN because for a child process instance the entity links are created before the entity (see ProcessTaskActivityBehavior) + if (referenceScopeId != null && ScopeTypes.CMMN.equals(referenceScopeType)) { + CaseInstanceEntity referenceScopeInstance = cmmnEngineConfiguration.getCaseInstanceEntityManager().findById(referenceScopeId); + if (referenceScopeInstance != null) { + return isHistoryEnabled(referenceScopeInstance.getCaseDefinitionId()); + } + } + + return true; } @Override diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java index 20087ffc294..f66dd7e47a8 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java @@ -33,15 +33,15 @@ public interface ProcessInstanceService { /** * Starts a process instance without a reference to a plan item instance (i.e. non-blocking behavior). */ - String startProcessInstanceByKey(String processDefinitionKey, String predefinedProcessInstanceId, String stageInstanceId, - String tenantId, Boolean fallbackToDefaultTenant, String parentDeploymentId, Map inParametersMap, String businessKey, + String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId, + String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome); /** * Starts a process instance with a reference to a plan item instance (i.e. blocking behavior). */ - String startProcessInstanceByKey(String processDefinitionKey, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, - String tenantId, Boolean fallbackToDefaultTenant, String parentDeploymentId, Map inParametersMap, String businessKey, + String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, + String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome); /** @@ -74,4 +74,19 @@ String startProcessInstanceByKey(String processDefinitionKey, String predefinedP */ List getOutputParametersOfCaseTask(String executionId); + /** + * Resolves the process definition id from the given key and parameters. + */ + default String resolveProcessDefinitionId(String processDefinitionKey, String tenantId, + Boolean fallbackToDefaultTenant, String parentDeploymentId) { + return null; + } + + /** + * Checks whether history is enabled for the given process definition id. + */ + default boolean isHistoryEnabledForProcessDefinitionId(String processDefinitionId) { + return true; + } + } diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelper.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelper.java index b24d31a8947..98a0ad5758f 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelper.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelper.java @@ -13,6 +13,7 @@ package org.flowable.cmmn.engine.impl.runtime; import org.flowable.cmmn.api.history.HistoricCaseInstance; +import org.flowable.cmmn.api.repository.CaseDefinition; import org.flowable.cmmn.api.runtime.CaseInstanceBuilder; import org.flowable.cmmn.engine.impl.persistence.entity.CaseInstanceEntity; import org.flowable.common.engine.impl.callback.CallbackData; @@ -36,6 +37,9 @@ public interface CaseInstanceHelper { */ CaseInstanceEntity copyHistoricCaseInstanceToRuntime(HistoricCaseInstance caseInstance); + CaseDefinition resolveCaseDefinition(String caseDefinitionKey, String tenantId, + boolean fallbackToDefaultTenant, String parentDeploymentId); + void callCaseInstanceStateChangeCallbacks(CallbackData callbackData); } diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelperImpl.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelperImpl.java index c9e4992c686..4b03be3bbb9 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelperImpl.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceHelperImpl.java @@ -112,6 +112,52 @@ public CaseInstanceEntity copyHistoricCaseInstanceToRuntime(HistoricCaseInstance return caseInstanceEntity; } + @Override + public CaseDefinition resolveCaseDefinition(String caseDefinitionKey, String tenantId, + boolean fallbackToDefaultTenant, String parentDeploymentId) { + CaseDefinitionEntityManager caseDefinitionEntityManager = cmmnEngineConfiguration.getCaseDefinitionEntityManager(); + CaseDefinition caseDefinition = null; + + if (tenantId != null && !CmmnEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { + if (parentDeploymentId != null) { + caseDefinition = caseDefinitionEntityManager + .findCaseDefinitionByParentDeploymentAndKeyAndTenantId(parentDeploymentId, caseDefinitionKey, tenantId); + } + if (caseDefinition == null) { + caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKeyAndTenantId(caseDefinitionKey, tenantId); + } + if (caseDefinition == null && fallbackToDefaultTenant) { + String defaultTenant = cmmnEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(tenantId, ScopeTypes.CMMN, caseDefinitionKey); + if (StringUtils.isNotEmpty(defaultTenant)) { + caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKeyAndTenantId(caseDefinitionKey, defaultTenant); + } else { + caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKey(caseDefinitionKey); + } + } + } else { + if (parentDeploymentId != null) { + caseDefinition = caseDefinitionEntityManager.findCaseDefinitionByParentDeploymentAndKey(parentDeploymentId, caseDefinitionKey); + } + if (caseDefinition == null) { + caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKey(caseDefinitionKey); + } + } + + if (caseDefinition == null) { + if (tenantId == null || CmmnEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { + throw new FlowableObjectNotFoundException("No case definition found for key " + caseDefinitionKey, CaseDefinition.class); + } else if (fallbackToDefaultTenant) { + throw new FlowableObjectNotFoundException( + "Case definition was not found by key '" + caseDefinitionKey + "'. Fallback to default tenant was also used."); + } else { + throw new FlowableObjectNotFoundException( + "Case definition was not found by key '" + caseDefinitionKey + "' and tenant '" + tenantId + "'"); + } + } + + return caseDefinition; + } + protected CaseDefinition getCaseDefinition(CaseInstanceBuilder caseInstanceBuilder, CommandContext commandContext) { CaseDefinition caseDefinition = null; if (caseInstanceBuilder.getCaseDefinitionId() != null) { @@ -121,53 +167,17 @@ protected CaseDefinition getCaseDefinition(CaseInstanceBuilder caseInstanceBuild } else if (caseInstanceBuilder.getCaseDefinitionKey() != null) { String caseDefinitionKey = caseInstanceBuilder.getCaseDefinitionKey(); - CaseDefinitionEntityManager caseDefinitionEntityManager = cmmnEngineConfiguration.getCaseDefinitionEntityManager(); String tenantId = caseInstanceBuilder.getTenantId(); String parentDeploymentId = caseInstanceBuilder.getCaseDefinitionParentDeploymentId(); - if (tenantId == null || CmmnEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { - - if (parentDeploymentId != null) { - caseDefinition = caseDefinitionEntityManager.findCaseDefinitionByParentDeploymentAndKey(parentDeploymentId, caseDefinitionKey); - } - - if (caseDefinition == null) { - caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKey(caseDefinitionKey); - } - if (caseDefinition == null) { - throw new FlowableObjectNotFoundException("No case definition found for key " + caseDefinitionKey, CaseDefinition.class); - } - - } else if (!CmmnEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { - if (parentDeploymentId != null) { - caseDefinition = caseDefinitionEntityManager - .findCaseDefinitionByParentDeploymentAndKeyAndTenantId(parentDeploymentId, caseDefinitionKey, tenantId); - } - - if (caseDefinition == null) { - caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKeyAndTenantId(caseDefinitionKey, tenantId); - } + caseDefinition = resolveCaseDefinition(caseDefinitionKey, tenantId, + caseInstanceBuilder.isFallbackToDefaultTenant() || cmmnEngineConfiguration.isFallbackToDefaultTenant(), + parentDeploymentId); - if (caseDefinition == null) { - if (caseInstanceBuilder.isFallbackToDefaultTenant() || cmmnEngineConfiguration.isFallbackToDefaultTenant()) { - String defaultTenant = cmmnEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(tenantId, ScopeTypes.CMMN, caseDefinitionKey); - if (StringUtils.isNotEmpty(defaultTenant)) { - caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKeyAndTenantId(caseDefinitionKey, defaultTenant); - caseInstanceBuilder.overrideCaseDefinitionTenantId(tenantId); - - } else { - caseDefinition = caseDefinitionEntityManager.findLatestCaseDefinitionByKey(caseDefinitionKey); - } - - if (caseDefinition == null) { - throw new FlowableObjectNotFoundException( - "Case definition was not found by key '" + caseDefinitionKey + "'. Fallback to default tenant was also used."); - } - } else { - throw new FlowableObjectNotFoundException( - "Case definition was not found by key '" + caseDefinitionKey + "' and tenant '" + tenantId + "'"); - } - } + if (caseDefinition != null && tenantId != null && !CmmnEngineConfiguration.NO_TENANT_ID.equals(tenantId) + && !tenantId.equals(caseDefinition.getTenantId())) { + // Case definition comes from the fallback to the default tenant + caseInstanceBuilder.overrideCaseDefinitionTenantId(tenantId); } } else { throw new FlowableIllegalArgumentException("caseDefinitionKey and caseDefinitionId are null"); diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/util/EntityLinkUtil.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/util/EntityLinkUtil.java index 85567ebae6e..d5f8e834c68 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/util/EntityLinkUtil.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/util/EntityLinkUtil.java @@ -33,7 +33,14 @@ public class EntityLinkUtil { public static void createEntityLinks(String scopeId, String subScopeId, String parentElementId, String referenceScopeId, String referenceScopeType, CmmnEngineConfiguration cmmnEngineConfiguration) { - + + createEntityLinks(scopeId, subScopeId, parentElementId, referenceScopeId, referenceScopeType, cmmnEngineConfiguration, true); + } + + public static void createEntityLinks(String scopeId, String subScopeId, String parentElementId, + String referenceScopeId, String referenceScopeType, CmmnEngineConfiguration cmmnEngineConfiguration, + boolean createHistoricEntityLinks) { + // scopeId is the process instance in which this is being created // referenceScopeId is CaseTask, HumanTask, etc. @@ -59,8 +66,8 @@ public static void createEntityLinks(String scopeId, String subScopeId, String p } } - copyAndCreateEntityLink(subScopeId, parentElementId, referenceScopeId, referenceScopeType, - newHierarchyType, parentEntityLink, entityLinkService, historyManager); + copyAndCreateEntityLink(subScopeId, parentElementId, referenceScopeId, referenceScopeType, + newHierarchyType, parentEntityLink, entityLinkService, historyManager, createHistoricEntityLinks); parentIds.add(parentEntityLink.getScopeId()); } @@ -82,12 +89,14 @@ public static void createEntityLinks(String scopeId, String subScopeId, String p rootScopeType = ScopeTypes.CMMN; } - createEntityLink(scopeId, subScopeId, parentElementId, referenceScopeId, referenceScopeType, - hierarchyType, rootScopeId, rootScopeType, entityLinkService, historyManager); + createEntityLink(scopeId, subScopeId, parentElementId, referenceScopeId, referenceScopeType, hierarchyType, + rootScopeId, rootScopeType, entityLinkService, historyManager, createHistoricEntityLinks); } + protected static EntityLinkEntity copyAndCreateEntityLink(String subScopeId, String parentElementId, String referenceScopeId, String referenceScopeType, String hierarchyType, - EntityLink parentEntityLink, EntityLinkService entityLinkService, CmmnHistoryManager historyManager) { + EntityLink parentEntityLink, EntityLinkService entityLinkService, CmmnHistoryManager historyManager, + boolean createHistoricEntityLinks) { EntityLinkEntity newEntityLink = (EntityLinkEntity) entityLinkService.createEntityLink(); newEntityLink.setLinkType(EntityLinkType.CHILD); @@ -103,14 +112,16 @@ protected static EntityLinkEntity copyAndCreateEntityLink(String subScopeId, Str newEntityLink.setRootScopeType(parentEntityLink.getRootScopeType()); entityLinkService.insertEntityLink(newEntityLink); - historyManager.recordEntityLinkCreated(newEntityLink); + if (createHistoricEntityLinks) { + historyManager.recordEntityLinkCreated(newEntityLink); + } return newEntityLink; } protected static EntityLinkEntity createEntityLink(String scopeId, String subScopeId, String parentElementId, String referenceScopeId, String referenceScopeType, String hierarchyType, String rootScopeId, String rootScopeType, - EntityLinkService entityLinkService, CmmnHistoryManager historyManager) { + EntityLinkService entityLinkService, CmmnHistoryManager historyManager, boolean createHistoricEntityLinks) { EntityLinkEntity newEntityLink = (EntityLinkEntity) entityLinkService.createEntityLink(); newEntityLink.setLinkType(EntityLinkType.CHILD); @@ -125,7 +136,9 @@ protected static EntityLinkEntity createEntityLink(String scopeId, String subSco newEntityLink.setRootScopeType(rootScopeType); entityLinkService.insertEntityLink(newEntityLink); - historyManager.recordEntityLinkCreated(newEntityLink); + if (createHistoricEntityLinks) { + historyManager.recordEntityLinkCreated(newEntityLink); + } return newEntityLink; } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java index 00be9918375..9cbec0aa9da 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java @@ -98,11 +98,6 @@ public void execute(DelegateExecution execution) { } } - if (processEngineConfiguration.isEnableEntityLinks()) { - EntityLinkUtil.createEntityLinks(execution.getProcessInstanceId(), execution.getId(), caseServiceTask.getId(), - caseInstanceId, ScopeTypes.CMMN); - } - String caseDefinitionKey = getCaseDefinitionKey(caseServiceTask.getCaseDefinitionKey(), execution, expressionManager); String parentDeploymentId = null; @@ -110,9 +105,19 @@ public void execute(DelegateExecution execution) { parentDeploymentId = ProcessDefinitionUtil.getDefinitionDeploymentId(execution.getProcessDefinitionId(), processEngineConfiguration); } - caseInstanceService.startCaseInstanceByKey(caseDefinitionKey, caseInstanceId, - caseInstanceName, businessKey, execution.getId(), execution.getTenantId(), caseServiceTask.isFallbackToDefaultTenant(), - parentDeploymentId, inParameters); + // Resolve the case definition first so we can check its history level for the entity links + String caseDefinitionId = caseInstanceService.resolveCaseDefinitionId(caseDefinitionKey, + execution.getTenantId(), caseServiceTask.isFallbackToDefaultTenant(), parentDeploymentId); + + if (processEngineConfiguration.isEnableEntityLinks()) { + boolean createHistoricEntityLinks = caseInstanceService.isHistoryEnabledForCaseDefinitionId(caseDefinitionId); + + EntityLinkUtil.createEntityLinks(execution.getProcessInstanceId(), execution.getId(), caseServiceTask.getId(), + caseInstanceId, ScopeTypes.CMMN, createHistoricEntityLinks); + } + + caseInstanceService.startCaseInstanceByKey(caseDefinitionId, caseInstanceId, + caseInstanceName, businessKey, execution.getId(), execution.getTenantId(), inParameters); // Bidirectional storing of reference to avoid queries later on executionEntity.setReferenceId(caseInstanceId); diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/StartProcessInstanceCmd.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/StartProcessInstanceCmd.java index b9a281af6c7..932df339a22 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/StartProcessInstanceCmd.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/StartProcessInstanceCmd.java @@ -32,7 +32,6 @@ import org.flowable.engine.ProcessEngineConfiguration; import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.flowable.engine.impl.persistence.deploy.DeploymentManager; -import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityManager; import org.flowable.engine.impl.runtime.ProcessInstanceBuilderImpl; import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.impl.util.ProcessDefinitionUtil; @@ -264,64 +263,25 @@ protected boolean hasFormData() { } protected ProcessDefinition getProcessDefinition(ProcessEngineConfigurationImpl processEngineConfiguration, CommandContext commandContext) { - DeploymentManager deploymentCache = CommandContextUtil.getProcessEngineConfiguration(commandContext).getDeploymentManager(); - ProcessDefinitionEntityManager processDefinitionEntityManager = processEngineConfiguration.getProcessDefinitionEntityManager(); - // Find the process definition ProcessDefinition processDefinition = null; if (processDefinitionId != null) { + DeploymentManager deploymentCache = processEngineConfiguration.getDeploymentManager(); processDefinition = deploymentCache.findDeployedProcessDefinitionById(processDefinitionId); if (processDefinition == null) { throw new FlowableObjectNotFoundException("No process definition found for id = '" + processDefinitionId + "'", ProcessDefinition.class); } - } else if (processDefinitionKey != null && (tenantId == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId))) { - - if (processDefinitionParentDeploymentId != null) { - processDefinition = processDefinitionEntityManager - .findProcessDefinitionByParentDeploymentAndKey(processDefinitionParentDeploymentId, processDefinitionKey); - } - - if (processDefinition == null) { - processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKey(processDefinitionKey); - } - - if (processDefinition == null) { - throw new FlowableObjectNotFoundException("No process definition found for key '" + processDefinitionKey + "'", ProcessDefinition.class); - } - - } else if (processDefinitionKey != null && tenantId != null && !ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { + } else if (processDefinitionKey != null) { + processDefinition = processEngineConfiguration.getProcessInstanceHelper() + .resolveProcessDefinition(processDefinitionKey, tenantId, + fallbackToDefaultTenant || processEngineConfiguration.isFallbackToDefaultTenant(), + processDefinitionParentDeploymentId, processEngineConfiguration); - if (processDefinitionParentDeploymentId != null) { - processDefinition = processDefinitionEntityManager - .findProcessDefinitionByParentDeploymentAndKeyAndTenantId(processDefinitionParentDeploymentId, processDefinitionKey, tenantId); - } - - if (processDefinition == null) { - processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId); - } - - if (processDefinition == null) { - if (fallbackToDefaultTenant || processEngineConfiguration.isFallbackToDefaultTenant()) { - String defaultTenant = processEngineConfiguration.getDefaultTenantProvider().getDefaultTenant(tenantId, ScopeTypes.BPMN, processDefinitionKey); - if (StringUtils.isNotEmpty(defaultTenant)) { - processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, defaultTenant); - if (processDefinition != null) { - overrideDefinitionTenantId = tenantId; - } - - } else { - processDefinition = processDefinitionEntityManager.findLatestProcessDefinitionByKey(processDefinitionKey); - } - - if (processDefinition == null) { - throw new FlowableObjectNotFoundException("No process definition found for key '" + processDefinitionKey + - "'. Fallback to default tenant was also applied.", ProcessDefinition.class); - } - } else { - throw new FlowableObjectNotFoundException("Process definition with key '" + processDefinitionKey + - "' and tenantId '"+ tenantId +"' was not found", ProcessDefinition.class); - } + if (tenantId != null && !ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId) + && !tenantId.equals(processDefinition.getTenantId())) { + // Process definition comes from the fallback to the default tenant + overrideDefinitionTenantId = tenantId; } } else { diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java index c8a66b97d99..2c75cd1cbe3 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java @@ -28,15 +28,30 @@ public interface CaseInstanceService { */ String generateNewCaseInstanceId(); - String startCaseInstanceByKey(String caseDefinitionKey, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, - String executionId, String tenantId, boolean fallbackToDefaultTenant, String parentDeploymentId, Map inParametersMap); - + String startCaseInstanceByKey(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, + String executionId, String tenantId, Map inParametersMap); + void handleSignalEvent(EventSubscriptionEntity eventSubscription, Map variables); void deleteCaseInstance(String caseInstanceId); void deleteCaseInstancesForExecutionId(String executionId); - + void deleteCaseInstanceWithoutAgenda(String caseInstanceId); + /** + * Resolves the case definition id from the given key and parameters. + */ + default String resolveCaseDefinitionId(String caseDefinitionKey, String tenantId, + boolean fallbackToDefaultTenant, String parentDeploymentId) { + return null; + } + + /** + * Checks whether history is enabled for the given case definition id. + */ + default boolean isHistoryEnabledForCaseDefinitionId(String caseDefinitionId) { + return true; + } + } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java index dd0ae4198cf..bb0d62466d6 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java @@ -311,8 +311,24 @@ protected String getProcessDefinitionId(IdentityLinkEntity identityLink) { @Override public boolean isHistoryEnabledForEntityLink(EntityLinkEntity entityLink) { + // Check if history is enabled for the source scope String processDefinitionId = getProcessDefinitionId(entityLink); - return isHistoryEnabled(processDefinitionId); + if (!isHistoryEnabled(processDefinitionId)) { + return false; + } + + // Also check the history level of the reference scope (if it is NONE we should not create the entity link) + String referenceScopeId = entityLink.getReferenceScopeId(); + String referenceScopeType = entityLink.getReferenceScopeType(); + // Check that the scope type is BPMN because for a child case instance the entity links are created before the entity (see CaseTaskActivityBehavior) + if (referenceScopeId != null && ScopeTypes.BPMN.equals(referenceScopeType)) { + ExecutionEntity referenceScopeExecution = processEngineConfiguration.getExecutionEntityManager().findById(referenceScopeId); + if (referenceScopeExecution != null) { + return isHistoryEnabled(referenceScopeExecution.getProcessDefinitionId()); + } + } + + return true; } @Override diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/EntityLinkUtil.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/EntityLinkUtil.java index d3ec43a1d58..bf4b7124627 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/EntityLinkUtil.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/EntityLinkUtil.java @@ -33,7 +33,13 @@ public class EntityLinkUtil { public static void createEntityLinks(String scopeId, String subScopeId, String parentElementId, String referenceScopeId, String referenceScopeType) { - + + createEntityLinks(scopeId, subScopeId, parentElementId, referenceScopeId, referenceScopeType, true); + } + + public static void createEntityLinks(String scopeId, String subScopeId, String parentElementId, + String referenceScopeId, String referenceScopeType, boolean createHistoricEntityLinks) { + // scopeId is the process instance in which this is being created // referenceScopeId is CallActivity, CaseTask, User @@ -60,8 +66,8 @@ public static void createEntityLinks(String scopeId, String subScopeId, String p } } - copyAndCreateEntityLink(subScopeId, parentElementId, referenceScopeId, referenceScopeType, - newHierarchyType, parentEntityLink, entityLinkService, historyManager); + copyAndCreateEntityLink(subScopeId, parentElementId, referenceScopeId, referenceScopeType, + newHierarchyType, parentEntityLink, entityLinkService, historyManager, createHistoricEntityLinks); parentIds.add(parentEntityLink.getScopeId()); } @@ -83,12 +89,14 @@ public static void createEntityLinks(String scopeId, String subScopeId, String p rootScopeType = ScopeTypes.BPMN; } - createEntityLink(scopeId, subScopeId, parentElementId, referenceScopeId, referenceScopeType, hierarchyType, - rootScopeId, rootScopeType, entityLinkService, historyManager); + createEntityLink(scopeId, subScopeId, parentElementId, referenceScopeId, referenceScopeType, hierarchyType, + rootScopeId, rootScopeType, entityLinkService, historyManager, createHistoricEntityLinks); } + protected static EntityLinkEntity copyAndCreateEntityLink(String subScopeId, String parentElementId, String referenceScopeId, String referenceScopeType, String hierarchyType, - EntityLink parentEntityLink, EntityLinkService entityLinkService, HistoryManager historyManager) { + EntityLink parentEntityLink, EntityLinkService entityLinkService, HistoryManager historyManager, + boolean createHistoricEntityLinks) { EntityLinkEntity newEntityLink = (EntityLinkEntity) entityLinkService.createEntityLink(); newEntityLink.setLinkType(EntityLinkType.CHILD); @@ -104,14 +112,16 @@ protected static EntityLinkEntity copyAndCreateEntityLink(String subScopeId, Str newEntityLink.setRootScopeType(parentEntityLink.getRootScopeType()); entityLinkService.insertEntityLink(newEntityLink); - historyManager.recordEntityLinkCreated(newEntityLink); + if (createHistoricEntityLinks) { + historyManager.recordEntityLinkCreated(newEntityLink); + } return newEntityLink; } protected static EntityLinkEntity createEntityLink(String scopeId, String subScopeId, String parentElementId, String referenceScopeId, String referenceScopeType, String hierarchyType, String rootScopeId, String rootScopeType, - EntityLinkService entityLinkService, HistoryManager historyManager) { + EntityLinkService entityLinkService, HistoryManager historyManager, boolean createHistoricEntityLinks) { EntityLinkEntity newEntityLink = (EntityLinkEntity) entityLinkService.createEntityLink(); newEntityLink.setLinkType(EntityLinkType.CHILD); @@ -126,9 +136,11 @@ protected static EntityLinkEntity createEntityLink(String scopeId, String subSco newEntityLink.setRootScopeType(rootScopeType); entityLinkService.insertEntityLink(newEntityLink); - historyManager.recordEntityLinkCreated(newEntityLink); + if (createHistoricEntityLinks) { + historyManager.recordEntityLinkCreated(newEntityLink); + } return newEntityLink; } - -} \ No newline at end of file + +} 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 17c1b0c5866..28005d0b47e 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 @@ -36,6 +36,7 @@ import org.flowable.bpmn.model.ValuedDataObject; import org.flowable.bpmn.model.VariableListenerEventDefinition; import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.api.FlowableObjectNotFoundException; import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher; import org.flowable.common.engine.api.scope.ScopeTypes; @@ -46,6 +47,7 @@ import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.common.engine.impl.logging.LoggingSessionConstants; import org.flowable.common.engine.impl.util.CollectionUtil; +import org.flowable.engine.ProcessEngineConfiguration; import org.flowable.engine.compatibility.Flowable5CompatibilityHandler; import org.flowable.engine.delegate.event.impl.FlowableEventBuilder; import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; @@ -54,6 +56,7 @@ import org.flowable.engine.impl.jobexecutor.TimerEventHandler; import org.flowable.engine.impl.jobexecutor.TriggerTimerEventJobHandler; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; +import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntityManager; import org.flowable.engine.impl.runtime.callback.ProcessInstanceState; import org.flowable.engine.interceptor.StartProcessInstanceAfterContext; import org.flowable.engine.interceptor.StartProcessInstanceBeforeContext; @@ -548,6 +551,59 @@ protected Map processDataObjects(Collection da return variablesMap; } + public ProcessDefinition resolveProcessDefinition(String processDefinitionKey, String tenantId, + boolean fallbackToDefaultTenant, String parentDeploymentId, + ProcessEngineConfigurationImpl processEngineConfiguration) { + ProcessDefinitionEntityManager processDefinitionEntityManager = processEngineConfiguration.getProcessDefinitionEntityManager(); + ProcessDefinition processDefinition = null; + + if (tenantId != null && !ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { + if (parentDeploymentId != null) { + processDefinition = processDefinitionEntityManager + .findProcessDefinitionByParentDeploymentAndKeyAndTenantId(parentDeploymentId, processDefinitionKey, tenantId); + } + if (processDefinition == null) { + processDefinition = processDefinitionEntityManager + .findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, tenantId); + } + if (processDefinition == null && fallbackToDefaultTenant) { + String defaultTenant = processEngineConfiguration.getDefaultTenantProvider() + .getDefaultTenant(tenantId, ScopeTypes.BPMN, processDefinitionKey); + if (StringUtils.isNotEmpty(defaultTenant)) { + processDefinition = processDefinitionEntityManager + .findLatestProcessDefinitionByKeyAndTenantId(processDefinitionKey, defaultTenant); + } else { + processDefinition = processDefinitionEntityManager + .findLatestProcessDefinitionByKey(processDefinitionKey); + } + } + } else { + if (parentDeploymentId != null) { + processDefinition = processDefinitionEntityManager + .findProcessDefinitionByParentDeploymentAndKey(parentDeploymentId, processDefinitionKey); + } + if (processDefinition == null) { + processDefinition = processDefinitionEntityManager + .findLatestProcessDefinitionByKey(processDefinitionKey); + } + } + + if (processDefinition == null) { + if (tenantId == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(tenantId)) { + throw new FlowableObjectNotFoundException( + "No process definition found for key '" + processDefinitionKey + "'", ProcessDefinition.class); + } else if (fallbackToDefaultTenant) { + throw new FlowableObjectNotFoundException( + "No process definition found for key '" + processDefinitionKey + "'. Fallback to default tenant was also applied.", ProcessDefinition.class); + } else { + throw new FlowableObjectNotFoundException( + "Process definition with key '" + processDefinitionKey + "' and tenantId '" + tenantId + "' was not found", ProcessDefinition.class); + } + } + + return processDefinition; + } + public void callCaseInstanceStateChangeCallbacks(CommandContext commandContext, ProcessInstance processInstance, String oldState, String newState) { if (processInstance.getCallbackId() != null && processInstance.getCallbackType() != null) { Map> caseInstanceCallbacks = CommandContextUtil From 43185a8a362af097fad92d198a25b63e90069a13 Mon Sep 17 00:00:00 2001 From: BertMatthys <84137009+BertMatthys@users.noreply.github.com> Date: Mon, 16 Mar 2026 16:48:06 +0100 Subject: [PATCH 2/2] Cleanup comments, function names + no default impl needed for CaseInstanceService/ProcessInstanceService methods --- .../impl/cmmn/DefaultCaseInstanceService.java | 2 +- .../process/DefaultProcessInstanceService.java | 6 +++--- .../behavior/impl/ProcessTaskActivityBehavior.java | 4 ++-- .../DefaultCmmnHistoryConfigurationSettings.java | 2 +- .../impl/process/ProcessInstanceService.java | 14 +++++--------- .../bpmn/behavior/CaseTaskActivityBehavior.java | 2 +- .../engine/impl/cmmn/CaseInstanceService.java | 12 ++++-------- .../DefaultHistoryConfigurationSettings.java | 2 +- 8 files changed, 18 insertions(+), 26 deletions(-) diff --git a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java index a93e875a626..bbca1e2adde 100644 --- a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java +++ b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java @@ -52,7 +52,7 @@ public String generateNewCaseInstanceId() { } @Override - public String startCaseInstanceByKey(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, + public String startCaseInstance(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, String executionId, String tenantId, Map inParametersMap) { CaseInstanceBuilder caseInstanceBuilder = cmmnEngineConfiguration.getCmmnRuntimeService().createCaseInstanceBuilder(); diff --git a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java index b4ebe42831e..f6545e0e343 100644 --- a/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java +++ b/modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/process/DefaultProcessInstanceService.java @@ -57,16 +57,16 @@ public String generateNewProcessInstanceId() { } @Override - public String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId, + public String startProcessInstance(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId, String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome) { - return startProcessInstanceByKey(processDefinitionId, predefinedProcessInstanceId, null, stageInstanceId, tenantId, + return startProcessInstance(processDefinitionId, predefinedProcessInstanceId, null, stageInstanceId, tenantId, inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); } @Override - public String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, + public String startProcessInstance(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome) { diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java index 59c890aab64..36b54dbad12 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/ProcessTaskActivityBehavior.java @@ -131,11 +131,11 @@ public void execute(CommandContext commandContext, PlanItemInstanceEntity planIt planItemInstanceEntity.getPlanItemDefinitionId(), processInstanceId, ScopeTypes.BPMN, cmmnEngineConfiguration, createHistoricEntityLinks); } - processInstanceService.startProcessInstanceByKey(processDefinitionId, processInstanceId, planItemInstanceEntity.getId(), planItemInstanceEntity.getStageInstanceId(), + processInstanceService.startProcessInstance(processDefinitionId, processInstanceId, planItemInstanceEntity.getId(), planItemInstanceEntity.getStageInstanceId(), planItemInstanceEntity.getTenantId(), inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); } else { - processInstanceService.startProcessInstanceByKey(processDefinitionId, processInstanceId, planItemInstanceEntity.getStageInstanceId(), + processInstanceService.startProcessInstance(processDefinitionId, processInstanceId, planItemInstanceEntity.getStageInstanceId(), planItemInstanceEntity.getTenantId(), inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome); } diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java index 1ba89e267d0..f430e6852d2 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/DefaultCmmnHistoryConfigurationSettings.java @@ -254,7 +254,7 @@ public boolean isHistoryEnabledForEntityLink(EntityLinkEntity entityLink) { // Also check the history level of the reference scope (if it is NONE we should not create the entity link) String referenceScopeId = entityLink.getReferenceScopeId(); String referenceScopeType = entityLink.getReferenceScopeType(); - // Check that the scope type is CMMN because for a child process instance the entity links are created before the entity (see ProcessTaskActivityBehavior) + // Only for CMMN scope type because for a child process instance the entity links are created before the entity (see ProcessTaskActivityBehavior) if (referenceScopeId != null && ScopeTypes.CMMN.equals(referenceScopeType)) { CaseInstanceEntity referenceScopeInstance = cmmnEngineConfiguration.getCaseInstanceEntityManager().findById(referenceScopeId); if (referenceScopeInstance != null) { diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java index f66dd7e47a8..7a1ad0e39f7 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/process/ProcessInstanceService.java @@ -33,14 +33,14 @@ public interface ProcessInstanceService { /** * Starts a process instance without a reference to a plan item instance (i.e. non-blocking behavior). */ - String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId, + String startProcessInstance(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId, String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome); /** * Starts a process instance with a reference to a plan item instance (i.e. blocking behavior). */ - String startProcessInstanceByKey(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, + String startProcessInstance(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId, String tenantId, Map inParametersMap, String businessKey, Map variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome); @@ -77,16 +77,12 @@ String startProcessInstanceByKey(String processDefinitionId, String predefinedPr /** * Resolves the process definition id from the given key and parameters. */ - default String resolveProcessDefinitionId(String processDefinitionKey, String tenantId, - Boolean fallbackToDefaultTenant, String parentDeploymentId) { - return null; - } + String resolveProcessDefinitionId(String processDefinitionKey, String tenantId, + Boolean fallbackToDefaultTenant, String parentDeploymentId); /** * Checks whether history is enabled for the given process definition id. */ - default boolean isHistoryEnabledForProcessDefinitionId(String processDefinitionId) { - return true; - } + boolean isHistoryEnabledForProcessDefinitionId(String processDefinitionId); } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java index 9cbec0aa9da..9c64c7c08a4 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CaseTaskActivityBehavior.java @@ -116,7 +116,7 @@ public void execute(DelegateExecution execution) { caseInstanceId, ScopeTypes.CMMN, createHistoricEntityLinks); } - caseInstanceService.startCaseInstanceByKey(caseDefinitionId, caseInstanceId, + caseInstanceService.startCaseInstance(caseDefinitionId, caseInstanceId, caseInstanceName, businessKey, execution.getId(), execution.getTenantId(), inParameters); // Bidirectional storing of reference to avoid queries later on diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java index 2c75cd1cbe3..83984c9edbe 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmmn/CaseInstanceService.java @@ -28,7 +28,7 @@ public interface CaseInstanceService { */ String generateNewCaseInstanceId(); - String startCaseInstanceByKey(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, + String startCaseInstance(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey, String executionId, String tenantId, Map inParametersMap); void handleSignalEvent(EventSubscriptionEntity eventSubscription, Map variables); @@ -42,16 +42,12 @@ String startCaseInstanceByKey(String caseDefinitionId, String predefinedCaseInst /** * Resolves the case definition id from the given key and parameters. */ - default String resolveCaseDefinitionId(String caseDefinitionKey, String tenantId, - boolean fallbackToDefaultTenant, String parentDeploymentId) { - return null; - } + String resolveCaseDefinitionId(String caseDefinitionKey, String tenantId, + boolean fallbackToDefaultTenant, String parentDeploymentId); /** * Checks whether history is enabled for the given case definition id. */ - default boolean isHistoryEnabledForCaseDefinitionId(String caseDefinitionId) { - return true; - } + boolean isHistoryEnabledForCaseDefinitionId(String caseDefinitionId); } diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java index bb0d62466d6..59b248d0f2c 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/history/DefaultHistoryConfigurationSettings.java @@ -320,7 +320,7 @@ public boolean isHistoryEnabledForEntityLink(EntityLinkEntity entityLink) { // Also check the history level of the reference scope (if it is NONE we should not create the entity link) String referenceScopeId = entityLink.getReferenceScopeId(); String referenceScopeType = entityLink.getReferenceScopeType(); - // Check that the scope type is BPMN because for a child case instance the entity links are created before the entity (see CaseTaskActivityBehavior) + // Only for BPMN scope type because for a child case instance the entity links are created before the entity (see CaseTaskActivityBehavior) if (referenceScopeId != null && ScopeTypes.BPMN.equals(referenceScopeType)) { ExecutionEntity referenceScopeExecution = processEngineConfiguration.getExecutionEntityManager().findById(referenceScopeId); if (referenceScopeExecution != null) {