Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ public interface BpmnXMLConstants {

public static final String ATTRIBUTE_BUSINESS_KEY = "businessKey";
public static final String ATTRIBUTE_INHERIT_BUSINESS_KEY = "inheritBusinessKey";
public static final String ATTRIBUTE_INHERIT_VARIABLES = "inheritVariables";
public static final String ATTRIBUTE_SAME_DEPLOYMENT = "sameDeployment";
public static final String ATTRIBUTE_CALLED_ELEMENT_BINDING = "calledElementBinding";
public static final String ATTRIBUTE_FALLBACK_TO_DEFAULT_TENANT = "fallbackToDefaultTenant";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public class ServiceTaskXMLConverter extends BaseBpmnXMLConverter {
new ExtensionAttribute(ATTRIBUTE_CASE_TASK_CASE_INSTANCE_NAME),
new ExtensionAttribute(ATTRIBUTE_BUSINESS_KEY),
new ExtensionAttribute(ATTRIBUTE_INHERIT_BUSINESS_KEY),
new ExtensionAttribute(ATTRIBUTE_INHERIT_VARIABLES),
new ExtensionAttribute(ATTRIBUTE_SAME_DEPLOYMENT),
new ExtensionAttribute(ATTRIBUTE_FALLBACK_TO_DEFAULT_TENANT),
new ExtensionAttribute(ATTRIBUTE_ID_VARIABLE_NAME));
Expand Down Expand Up @@ -236,6 +237,9 @@ protected void writeCaseServiceTaskAdditionalAttributes(BaseElement element, Bpm
if (caseServiceTask.isInheritBusinessKey()) {
writeQualifiedAttribute(ATTRIBUTE_INHERIT_BUSINESS_KEY, "true", xtw);
}
if (caseServiceTask.isInheritVariables()) {
writeQualifiedAttribute(ATTRIBUTE_INHERIT_VARIABLES, "true", xtw);
}
if (caseServiceTask.isSameDeployment()) {
writeQualifiedAttribute(ATTRIBUTE_SAME_DEPLOYMENT, "true", xtw);
}
Expand Down Expand Up @@ -432,6 +436,7 @@ protected void convertCaseServiceTaskXMLProperties(CaseServiceTask caseServiceTa

caseServiceTask.setBusinessKey(BpmnXMLUtil.getAttributeValue(ATTRIBUTE_BUSINESS_KEY, xtr));
caseServiceTask.setInheritBusinessKey(Boolean.parseBoolean(BpmnXMLUtil.getAttributeValue(ATTRIBUTE_INHERIT_BUSINESS_KEY, xtr)));
caseServiceTask.setInheritVariables(Boolean.parseBoolean(BpmnXMLUtil.getAttributeValue(ATTRIBUTE_INHERIT_VARIABLES, xtr)));
caseServiceTask.setSameDeployment(Boolean.valueOf(BpmnXMLUtil.getAttributeValue(ATTRIBUTE_SAME_DEPLOYMENT, xtr)));
caseServiceTask.setFallbackToDefaultTenant(Boolean.valueOf(BpmnXMLUtil.getAttributeValue(ATTRIBUTE_FALLBACK_TO_DEFAULT_TENANT, xtr)));
caseServiceTask.setCaseInstanceIdVariableName(BpmnXMLUtil.getAttributeValue(ATTRIBUTE_ID_VARIABLE_NAME, xtr));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void validateModel(BpmnModel model) {

assertThat(caseServiceTask.isFallbackToDefaultTenant()).isTrue();
assertThat(caseServiceTask.isSameDeployment()).isFalse();
assertThat(caseServiceTask.isInheritVariables()).isTrue();

List<IOParameter> parameters = caseServiceTask.getInParameters();
assertThat(parameters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
targetNamespace="http://www.flowable.org/test">

<process id="process" name="process1" isExecutable="true">
<serviceTask id="caseServiceTask" flowable:type="case" name="Case task" flowable:caseDefinitionKey="caseId" flowable:fallbackToDefaultTenant="true">
<serviceTask id="caseServiceTask" flowable:type="case" name="Case task" flowable:caseDefinitionKey="caseId" flowable:fallbackToDefaultTenant="true" flowable:inheritVariables="true">
<extensionElements>
<flowable:in source="test" target="test"></flowable:in>
<flowable:in sourceExpression="${test}" target="test"></flowable:in>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class CaseServiceTask extends ServiceTask implements HasOutParameters, Ha
protected boolean sameDeployment;
protected String businessKey;
protected boolean inheritBusinessKey;
protected boolean inheritVariables;
protected boolean fallbackToDefaultTenant;
protected String caseInstanceIdVariableName;

Expand Down Expand Up @@ -71,6 +72,14 @@ public void setInheritBusinessKey(boolean inheritBusinessKey) {
this.inheritBusinessKey = inheritBusinessKey;
}

public boolean isInheritVariables() {
return inheritVariables;
}

public void setInheritVariables(boolean inheritVariables) {
this.inheritVariables = inheritVariables;
}

public boolean isFallbackToDefaultTenant() {
return fallbackToDefaultTenant;
}
Expand Down Expand Up @@ -131,6 +140,7 @@ public void setValues(CaseServiceTask otherElement) {
setCaseInstanceName(otherElement.getCaseInstanceName());
setBusinessKey(otherElement.getBusinessKey());
setInheritBusinessKey(otherElement.isInheritBusinessKey());
setInheritVariables(otherElement.isInheritVariables());
setSameDeployment(otherElement.isSameDeployment());
setFallbackToDefaultTenant(otherElement.isFallbackToDefaultTenant());
setCaseInstanceIdVariableName(otherElement.getCaseInstanceIdVariableName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ protected CmmnElement convert(XMLStreamReader xtr, ConversionHelper conversionHe
caseTask.setInheritBusinessKey(Boolean.parseBoolean(inheritBusinessKey));
}

String inheritVariables = xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_INHERIT_VARIABLES);
if (inheritVariables != null) {
caseTask.setInheritVariables(Boolean.parseBoolean(inheritVariables));
}

String fallbackToDefaultTenantValue = xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_FALLBACK_TO_DEFAULT_TENANT);
if (fallbackToDefaultTenantValue != null) {
caseTask.setFallbackToDefaultTenant(Boolean.valueOf(fallbackToDefaultTenantValue));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public interface CmmnXmlConstants {
String ATTRIBUTE_FALLBACK_TO_DEFAULT_TENANT = "fallbackToDefaultTenant";
String ATTRIBUTE_BUSINESS_KEY = "businessKey";
String ATTRIBUTE_INHERIT_BUSINESS_KEY = "inheritBusinessKey";
String ATTRIBUTE_INHERIT_VARIABLES = "inheritVariables";
String ATTRIBUTE_ID_VARIABLE_NAME = "idVariableName";

String ELEMENT_CASE_REF_EXPRESSION = "caseRefExpression";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ protected CmmnElement convert(XMLStreamReader xtr, ConversionHelper conversionHe
processTask.setInheritBusinessKey(Boolean.parseBoolean(inheritBusinessKey));
}

String inheritVariables = xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_INHERIT_VARIABLES);
if (inheritVariables != null) {
processTask.setInheritVariables(Boolean.parseBoolean(inheritVariables));
}

String fallbackToDefaultTenantValue = xtr.getAttributeValue(CmmnXmlConstants.FLOWABLE_EXTENSIONS_NAMESPACE, CmmnXmlConstants.ATTRIBUTE_FALLBACK_TO_DEFAULT_TENANT);
if (fallbackToDefaultTenantValue != null) {
processTask.setFallbackToDefaultTenant(Boolean.parseBoolean(fallbackToDefaultTenantValue));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ protected void writePlanItemDefinitionSpecificAttributes(T planItemDefinition, X
if (planItemDefinition.isInheritBusinessKey()) {
xtw.writeAttribute(FLOWABLE_EXTENSIONS_PREFIX, FLOWABLE_EXTENSIONS_NAMESPACE, ATTRIBUTE_INHERIT_BUSINESS_KEY, String.valueOf(planItemDefinition.isInheritBusinessKey()));
}
if (planItemDefinition.isInheritVariables()) {
xtw.writeAttribute(FLOWABLE_EXTENSIONS_PREFIX, FLOWABLE_EXTENSIONS_NAMESPACE, ATTRIBUTE_INHERIT_VARIABLES, String.valueOf(planItemDefinition.isInheritVariables()));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public void validateModel(CmmnModel cmmnModel) {
assertThat(task1.getCaseRefExpression()).isEqualTo("caseDefinitionKey");
assertThat(task1.getFallbackToDefaultTenant()).isTrue();
assertThat(task1.isSameDeployment()).isTrue();
assertThat(task1.isInheritVariables()).isTrue();

assertThat(task1.getInParameters())
.extracting(IOParameter::getSource, IOParameter::getTarget)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void validateModel(CmmnModel cmmnModel) {
.isInstanceOfSatisfying(ProcessTask.class, task1 -> {
assertThat(task1.getProcessRefExpression()).isEqualTo("myTestProcess");
assertThat((task1.isSameDeployment())).isTrue();
assertThat(task1.isInheritVariables()).isTrue();

assertThat(task1.getInParameters()).isEmpty();
assertThat(task1.getOutParameters()).isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</sentry>

<task id="theTask" name="The Task" isBlocking="true" />
<caseTask id="theCase" isBlocking="true" flowable:fallbackToDefaultTenant="true" flowable:sameDeployment="true">
<caseTask id="theCase" isBlocking="true" flowable:fallbackToDefaultTenant="true" flowable:sameDeployment="true" flowable:inheritVariables="true">
<extensionElements>
<flowable:in source="testSource" target="testTarget"></flowable:in>
</extensionElements>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</humanTask>
<processTask id="oneprocesstask1" name="Process task" flowable:sameDeployment="true">
<processTask id="oneprocesstask1" name="Process task" flowable:sameDeployment="true" flowable:inheritVariables="true">
<processRefExpression><![CDATA[myTestProcess]]></processRefExpression>
</processTask>
</casePlanModel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public String generateNewCaseInstanceId() {

@Override
public String startCaseInstance(String caseDefinitionId, String predefinedCaseInstanceId, String caseInstanceName, String businessKey,
String executionId, String tenantId, Map<String, Object> inParametersMap) {
String executionId, String tenantId, Map<String, Object> inParametersMap, Map<String, Object> transientVariablesMap) {

CaseInstanceBuilder caseInstanceBuilder = cmmnEngineConfiguration.getCmmnRuntimeService().createCaseInstanceBuilder();
caseInstanceBuilder.caseDefinitionId(caseDefinitionId);
Expand All @@ -76,6 +76,10 @@ public String startCaseInstance(String caseDefinitionId, String predefinedCaseIn
caseInstanceBuilder.variable(target, inParametersMap.get(target));
}

if (transientVariablesMap != null && !transientVariablesMap.isEmpty()) {
caseInstanceBuilder.transientVariables(transientVariablesMap);
}

if (businessKey != null) {
caseInstanceBuilder.businessKey(businessKey);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ public String generateNewProcessInstanceId() {

@Override
public String startProcessInstance(String processDefinitionId, String predefinedProcessInstanceId, String stageInstanceId,
String tenantId, Map<String, Object> inParametersMap, String businessKey,
String tenantId, Map<String, Object> inParametersMap, Map<String, Object> transientVariablesMap, String businessKey,
Map<String, Object> variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome) {

return startProcessInstance(processDefinitionId, predefinedProcessInstanceId, null, stageInstanceId, tenantId,
inParametersMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome);
inParametersMap, transientVariablesMap, businessKey, variableFormVariables, variableFormInfo, variableFormOutcome);
}

@Override
public String startProcessInstance(String processDefinitionId, String predefinedProcessInstanceId, String planItemInstanceId, String stageInstanceId,
String tenantId, Map<String, Object> inParametersMap, String businessKey,
String tenantId, Map<String, Object> inParametersMap, Map<String, Object> transientVariablesMap, String businessKey,
Map<String, Object> variableFormVariables, FormInfo variableFormInfo, String variableFormOutcome) {

ProcessInstanceBuilder processInstanceBuilder = processEngineConfiguration.getRuntimeService().createProcessInstanceBuilder();
Expand All @@ -91,6 +91,10 @@ public String startProcessInstance(String processDefinitionId, String predefined
processInstanceBuilder.variable(target, inParametersMap.get(target));
}

if (transientVariablesMap != null && !transientVariablesMap.isEmpty()) {
processInstanceBuilder.transientVariables(transientVariablesMap);
}

if (businessKey != null) {
processInstanceBuilder.businessKey(businessKey);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -1603,4 +1604,90 @@ public void testParentProcessInstanceIdQuery() {
}
}

@Test
@CmmnDeployment
public void testCaseTaskInheritVariables() {
Deployment deployment = processEngineRepositoryService.createDeployment()
.addClasspathResource("org/flowable/cmmn/test/caseTaskInheritVariablesProcess.bpmn20.xml")
.deploy();

try {
ObjectNode jsonVariable = processEngineConfiguration.getObjectMapper().createObjectNode();
jsonVariable.put("field", "value");

Map<String, Object> variables = new HashMap<>();
variables.put("parentVar1", "hello");
variables.put("parentVar2", "world");
variables.put("parentVarJson", jsonVariable);
ProcessInstance processInstance = processEngineRuntimeService.createProcessInstanceBuilder()
.processDefinitionKey("inheritVariablesProcess")
.variables(variables)
.transientVariables(Collections.singletonMap("parentTransientVar", "temp"))
.start();

Execution caseTaskExecution = processEngineRuntimeService.createExecutionQuery()
.onlyChildExecutions()
.processInstanceId(processInstance.getId())
.activityId("caseServiceTask")
.singleResult();
assertThat(caseTaskExecution).isNotNull();

CaseInstance childCaseInstance = cmmnRuntimeService.createCaseInstanceQuery()
.caseInstanceCallbackId(caseTaskExecution.getId())
.caseInstanceCallbackType(CallbackTypes.EXECUTION_CHILD_CASE)
.singleResult();
assertThat(childCaseInstance).isNotNull();

// All parent process variables are inherited into the child case instance (like a call activity)
assertThat(cmmnRuntimeService.getVariable(childCaseInstance.getId(), "parentVar1")).isEqualTo("hello");

// JSON variables are inherited (deep copied, consistent with in parameter handling)
JsonNode childJson = (JsonNode) cmmnRuntimeService.getVariable(childCaseInstance.getId(), "parentVarJson");
assertThat(childJson.path("field").asString()).isEqualTo("value");

// An explicit in parameter takes precedence over the inherited variable
assertThat(cmmnRuntimeService.getVariable(childCaseInstance.getId(), "parentVar2")).isEqualTo("overridden");

// Transient variables are inherited as transient: available while the child starts (the child task
// name resolves the ${parentTransientVar} expression) but not persisted on the child.
assertThat(cmmnTaskService.createTaskQuery().caseInstanceId(childCaseInstance.getId()).singleResult().getName()).isEqualTo("temp");
assertThat(cmmnRuntimeService.getVariable(childCaseInstance.getId(), "parentTransientVar")).isNull();

} finally {
processEngineRepositoryService.deleteDeployment(deployment.getId(), true);
}
}

@Test
@CmmnDeployment(resources = "org/flowable/cmmn/test/caseTaskInheritVariablesDisabledChildCase.cmmn")
public void testCaseTaskInheritVariablesDisabled() {
Deployment deployment = processEngineRepositoryService.createDeployment()
.addClasspathResource("org/flowable/cmmn/test/caseTaskInheritVariablesDisabledProcess.bpmn20.xml")
.deploy();

try {
ProcessInstance processInstance = processEngineRuntimeService.startProcessInstanceByKey(
"inheritVariablesDisabledProcess", Collections.<String, Object>singletonMap("parentVar1", "hello"));

Execution caseTaskExecution = processEngineRuntimeService.createExecutionQuery()
.onlyChildExecutions()
.processInstanceId(processInstance.getId())
.activityId("caseServiceTask")
.singleResult();
assertThat(caseTaskExecution).isNotNull();

CaseInstance childCaseInstance = cmmnRuntimeService.createCaseInstanceQuery()
.caseInstanceCallbackId(caseTaskExecution.getId())
.caseInstanceCallbackType(CallbackTypes.EXECUTION_CHILD_CASE)
.singleResult();
assertThat(childCaseInstance).isNotNull();

// Without inheritVariables, parent variables are not copied into the child case
assertThat(cmmnRuntimeService.getVariable(childCaseInstance.getId(), "parentVar1")).isNull();

} finally {
processEngineRepositoryService.deleteDeployment(deployment.getId(), true);
}
}

}
Loading