You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by mc...@apache.org on 2026/04/07 13:11:24 UTC
(incubator-kie-kogito-runtimes) branch main updated: [main][incubator-kie-issues-2273] Fix multiple groups expression evaluation… (#4223)
This is an automated email from the ASF dual-hosted git repository.
mcimbalek pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git
The following commit(s) were added to refs/heads/main by this push:
new 3eb270044c [main][incubator-kie-issues-2273] Fix multiple groups expression evaluation… (#4223)
3eb270044c is described below
commit 3eb270044c06457007dcecbfb98c45553451561c
Author: Martin Cimbalek <ci...@gmail.com>
AuthorDate: Tue Apr 7 15:11:19 2026 +0200
[main][incubator-kie-issues-2273] Fix multiple groups expression evaluation… (#4223)
* [incubator-kie-issues-2273] Fix multiple groups expression evaluation bug
* simplify regexes and cleanUp logic
* Add spring boot integration test
---
.../org/jbpm/bpmn2/xml/AbstractNodeHandler.java | 24 +++--
.../main/java/org/jbpm/util/PatternConstants.java | 3 +-
.../manager_multiple_groups_variables.bpmn | 106 +++++++++++++++++++++
.../usertask/jpa/it/WsHumanTaskLifeCycleIT.java | 38 ++++++++
.../manager_multiple_groups_variables.bpmn | 106 +++++++++++++++++++++
.../usertask/jpa/it/WsHumanTaskLifeCycleIT.java | 40 ++++++++
6 files changed, 307 insertions(+), 10 deletions(-)
diff --git a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AbstractNodeHandler.java b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AbstractNodeHandler.java
index 91f850e25b..05149b40cb 100755
--- a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AbstractNodeHandler.java
+++ b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/AbstractNodeHandler.java
@@ -636,17 +636,23 @@ public abstract class AbstractNodeHandler extends BaseAbstractHandler implements
return assignments;
}
+ /**
+ * Simplifies variable expression in order to improve performance
+ *
+ * If the expression contains just once variable, we can skip MVEL expression evaluation
+ *
+ * @param expression MVEL expression to evaluate
+ * @return Variable name if expression evaluation is not needed, original expression otherwise
+ */
private String cleanUp(String expression) {
- // this is for user task expressions (they should be set as it is)
- if (expression.startsWith("[")) {
- return expression;
- }
- Matcher matcher = PatternConstants.PARAMETER_MATCHER.matcher(expression);
- String temp = expression;
- if (matcher.find()) {
- temp = matcher.group(1);
+ Matcher matcher = PatternConstants.SINGLE_PARAMETER_MATCHER.matcher(expression);
+ if (matcher.matches()) {
+ if (!matcher.group(1).contains(".")) {
+ return matcher.group(1);
+ }
}
- return temp.contains(".") ? expression : temp;
+
+ return expression;
}
private DataDefinition toDataExpression(String id, String expression) {
diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/util/PatternConstants.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/util/PatternConstants.java
index 1f7b478040..af99e19f1e 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/util/PatternConstants.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/util/PatternConstants.java
@@ -22,7 +22,8 @@ import java.util.regex.Pattern;
public class PatternConstants {
- public static final Pattern PARAMETER_MATCHER = Pattern.compile("#\\{([\\S|\\p{javaWhitespace}&&[^\\}]]+)\\}", Pattern.DOTALL);
+ public static final Pattern PARAMETER_MATCHER = Pattern.compile("#\\{([^}]+)\\}", Pattern.DOTALL);
+ public static final Pattern SINGLE_PARAMETER_MATCHER = Pattern.compile("#\\{([^}]+)\\}$");
public static final Pattern SIMPLE_TIME_DATE_MATCHER = Pattern.compile("([+-])?\\s*((\\d+)[Ww])?\\s*((\\d+)[Dd])?\\s*((\\d+)[Hh])?\\s*((\\d+)[Mm])?\\s*((\\d+)[Ss])?");
private PatternConstants() {
diff --git a/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/main/resources/manager_multiple_groups_variables.bpmn b/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/main/resources/manager_multiple_groups_variables.bpmn
new file mode 100644
index 0000000000..a31c5feb81
--- /dev/null
+++ b/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/main/resources/manager_multiple_groups_variables.bpmn
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you 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.
+ -->
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:bpsim="http://www.bpsim.org/schemas/1.0" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:drools="http://www.jboss.org/drools" id="_multiGroupVarTest" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www.jboss [...]
+ <bpmn2:itemDefinition id="__MGV_Task_SkippableInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__MGV_Task_TaskNameInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__MGV_Task_GroupIdInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="_group1Item" structureRef="String"/>
+ <bpmn2:itemDefinition id="_group2Item" structureRef="String"/>
+ <bpmn2:itemDefinition id="_group3Item" structureRef="String"/>
+ <bpmn2:collaboration id="_MGV_Collaboration" name="Default Collaboration">
+ <bpmn2:participant id="_MGV_Participant" name="Pool Participant" processRef="manager_multiple_groups_variables"/>
+ </bpmn2:collaboration>
+ <bpmn2:process id="manager_multiple_groups_variables" drools:packageName="com.example" drools:version="1.0" drools:adHoc="false" name="manager_multiple_groups_variables" isExecutable="true" processType="Public">
+ <bpmn2:property id="group1" itemSubjectRef="_group1Item" name="group1"/>
+ <bpmn2:property id="group2" itemSubjectRef="_group2Item" name="group2"/>
+ <bpmn2:property id="group3" itemSubjectRef="_group3Item" name="group3"/>
+ <bpmn2:sequenceFlow id="_MGV_Flow2" sourceRef="_MGV_Task" targetRef="_MGV_End"/>
+ <bpmn2:sequenceFlow id="_MGV_Flow1" sourceRef="_MGV_Start" targetRef="_MGV_Task"/>
+ <bpmn2:endEvent id="_MGV_End">
+ <bpmn2:incoming>_MGV_Flow2</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:userTask id="_MGV_Task" name="Task">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Task]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_MGV_Flow1</bpmn2:incoming>
+ <bpmn2:outgoing>_MGV_Flow2</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_MGV_Task_TaskNameInputX" drools:dtype="Object" itemSubjectRef="__MGV_Task_TaskNameInputXItem" name="TaskName"/>
+ <bpmn2:dataInput id="_MGV_Task_SkippableInputX" drools:dtype="Object" itemSubjectRef="__MGV_Task_SkippableInputXItem" name="Skippable"/>
+ <bpmn2:dataInput id="_MGV_Task_GroupIdInputX" drools:dtype="Object" itemSubjectRef="__MGV_Task_GroupIdInputXItem" name="GroupId"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_MGV_Task_TaskNameInputX</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_MGV_Task_SkippableInputX</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_MGV_Task_GroupIdInputX</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_MGV_Task_TaskNameInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[Task]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_MGV_Task_TaskNameInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_MGV_Task_SkippableInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[false]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_MGV_Task_SkippableInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_MGV_Task_GroupIdInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[#{group1},#{group2},#{group3}]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_MGV_Task_GroupIdInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:userTask>
+ <bpmn2:startEvent id="_MGV_Start">
+ <bpmn2:outgoing>_MGV_Flow1</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="manager_multiple_groups_variables">
+ <bpmndi:BPMNShape id="shape__MGV_Start" bpmnElement="_MGV_Start">
+ <dc:Bounds height="56" width="56" x="100" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__MGV_Task" bpmnElement="_MGV_Task">
+ <dc:Bounds height="102" width="154" x="236" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__MGV_End" bpmnElement="_MGV_End">
+ <dc:Bounds height="56" width="56" x="470" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="edge_shape__MGV_Start_to_shape__MGV_Task" bpmnElement="_MGV_Flow1">
+ <di:waypoint x="128" y="128"/>
+ <di:waypoint x="236" y="128"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="edge_shape__MGV_Task_to_shape__MGV_End" bpmnElement="_MGV_Flow2">
+ <di:waypoint x="313" y="128"/>
+ <di:waypoint x="498" y="128"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
+
+<!-- Made with Bob -->
diff --git a/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java b/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java
index 8b2a087221..0994d4a692 100644
--- a/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java
+++ b/quarkus/integration-tests/integration-tests-quarkus-wshumantasks/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java
@@ -622,6 +622,44 @@ public class WsHumanTaskLifeCycleIT {
isProcessCompleted(processId, pid);
}
+ @Test
+ public void testMultipleGroupsWithVariablesUserTaskLifeCycle() {
+ // This test verifies the fix for multi-variable expressions in BPMN
+ // The GroupId is defined as #{group1},#{group2},#{group3} in the BPMN
+ var user = "dave";
+ var group = "engineering";
+ var potentialGroups = new String[] { "hr", "engineering", "management" };
+ var processId = "manager_multiple_groups_variables";
+
+ // Start process with variables that will be resolved in GroupId expression
+ var pid = startProcessInstanceWithVariables(processId, Map.of(
+ "group1", "hr",
+ "group2", "engineering",
+ "group3", "management"));
+
+ var taskId = getTaskId(user, group, pid);
+
+ // Verify all three groups are present in potentialGroups
+ given()
+ .contentType(ContentType.JSON)
+ .when()
+ .queryParam("user", user)
+ .queryParam("group", group)
+ .get(USER_TASKS_INSTANCE_ENDPOINT, taskId)
+ .then()
+ .statusCode(200)
+ .body("id", equalTo(taskId))
+ .body("status.name", equalTo("Ready"))
+ .body("potentialUsers", equalTo(List.of()))
+ .body("potentialGroups", hasItems(potentialGroups));
+
+ claim(taskId, user, group);
+ start(taskId, user, group);
+ complete(taskId, user, group);
+
+ isProcessCompleted(processId, pid);
+ }
+
private void nominate(String taskId, String user, String status, String[] nominatedUsers) {
given()
.contentType(ContentType.JSON)
diff --git a/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/main/resources/manager_multiple_groups_variables.bpmn b/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/main/resources/manager_multiple_groups_variables.bpmn
new file mode 100644
index 0000000000..a31c5feb81
--- /dev/null
+++ b/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/main/resources/manager_multiple_groups_variables.bpmn
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you 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.
+ -->
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:bpsim="http://www.bpsim.org/schemas/1.0" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:drools="http://www.jboss.org/drools" id="_multiGroupVarTest" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www.jboss [...]
+ <bpmn2:itemDefinition id="__MGV_Task_SkippableInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__MGV_Task_TaskNameInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__MGV_Task_GroupIdInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="_group1Item" structureRef="String"/>
+ <bpmn2:itemDefinition id="_group2Item" structureRef="String"/>
+ <bpmn2:itemDefinition id="_group3Item" structureRef="String"/>
+ <bpmn2:collaboration id="_MGV_Collaboration" name="Default Collaboration">
+ <bpmn2:participant id="_MGV_Participant" name="Pool Participant" processRef="manager_multiple_groups_variables"/>
+ </bpmn2:collaboration>
+ <bpmn2:process id="manager_multiple_groups_variables" drools:packageName="com.example" drools:version="1.0" drools:adHoc="false" name="manager_multiple_groups_variables" isExecutable="true" processType="Public">
+ <bpmn2:property id="group1" itemSubjectRef="_group1Item" name="group1"/>
+ <bpmn2:property id="group2" itemSubjectRef="_group2Item" name="group2"/>
+ <bpmn2:property id="group3" itemSubjectRef="_group3Item" name="group3"/>
+ <bpmn2:sequenceFlow id="_MGV_Flow2" sourceRef="_MGV_Task" targetRef="_MGV_End"/>
+ <bpmn2:sequenceFlow id="_MGV_Flow1" sourceRef="_MGV_Start" targetRef="_MGV_Task"/>
+ <bpmn2:endEvent id="_MGV_End">
+ <bpmn2:incoming>_MGV_Flow2</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:userTask id="_MGV_Task" name="Task">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Task]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_MGV_Flow1</bpmn2:incoming>
+ <bpmn2:outgoing>_MGV_Flow2</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_MGV_Task_TaskNameInputX" drools:dtype="Object" itemSubjectRef="__MGV_Task_TaskNameInputXItem" name="TaskName"/>
+ <bpmn2:dataInput id="_MGV_Task_SkippableInputX" drools:dtype="Object" itemSubjectRef="__MGV_Task_SkippableInputXItem" name="Skippable"/>
+ <bpmn2:dataInput id="_MGV_Task_GroupIdInputX" drools:dtype="Object" itemSubjectRef="__MGV_Task_GroupIdInputXItem" name="GroupId"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_MGV_Task_TaskNameInputX</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_MGV_Task_SkippableInputX</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_MGV_Task_GroupIdInputX</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_MGV_Task_TaskNameInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[Task]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_MGV_Task_TaskNameInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_MGV_Task_SkippableInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[false]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_MGV_Task_SkippableInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_MGV_Task_GroupIdInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[#{group1},#{group2},#{group3}]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_MGV_Task_GroupIdInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ </bpmn2:userTask>
+ <bpmn2:startEvent id="_MGV_Start">
+ <bpmn2:outgoing>_MGV_Flow1</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="manager_multiple_groups_variables">
+ <bpmndi:BPMNShape id="shape__MGV_Start" bpmnElement="_MGV_Start">
+ <dc:Bounds height="56" width="56" x="100" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__MGV_Task" bpmnElement="_MGV_Task">
+ <dc:Bounds height="102" width="154" x="236" y="77"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__MGV_End" bpmnElement="_MGV_End">
+ <dc:Bounds height="56" width="56" x="470" y="100"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="edge_shape__MGV_Start_to_shape__MGV_Task" bpmnElement="_MGV_Flow1">
+ <di:waypoint x="128" y="128"/>
+ <di:waypoint x="236" y="128"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="edge_shape__MGV_Task_to_shape__MGV_End" bpmnElement="_MGV_Flow2">
+ <di:waypoint x="313" y="128"/>
+ <di:waypoint x="498" y="128"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+</bpmn2:definitions>
+
+<!-- Made with Bob -->
diff --git a/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java b/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java
index 53187afdfc..2f811265a2 100644
--- a/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java
+++ b/springboot/integration-tests/integration-tests-springboot-wshumantasks-it/src/test/java/org/jbpm/usertask/jpa/it/WsHumanTaskLifeCycleIT.java
@@ -631,6 +631,46 @@ public class WsHumanTaskLifeCycleIT {
isProcessCompleted(processId, pid);
}
+ @Test
+ public void testMultipleGroupsWithVariablesUserTaskLifeCycle() {
+ // This test verifies the fix for multi-variable expressions in BPMN
+ // The GroupId is defined as #{group1},#{group2},#{group3} in the BPMN
+ // and we pass the actual group names as process variables
+ var user = "dave";
+ var group = "engineering";
+ var potentialGroups = new String[] { "hr", "engineering", "management" };
+ var processId = "manager_multiple_groups_variables";
+
+ // Start process with variables that will be resolved in GroupId expression
+ var pid = startProcessInstanceWithVariables(processId, Map.of(
+ "group1", "hr",
+ "group2", "engineering",
+ "group3", "management"));
+
+ var taskId = getTaskId(user, group, pid);
+
+ // Verify all three groups are present in potentialGroups
+ // This would fail with the old implementation which only extracted the first variable
+ given()
+ .contentType(ContentType.JSON)
+ .when()
+ .queryParam("user", user)
+ .queryParam("group", group)
+ .get(USER_TASKS_INSTANCE_ENDPOINT, taskId)
+ .then()
+ .statusCode(200)
+ .body("id", equalTo(taskId))
+ .body("status.name", equalTo("Ready"))
+ .body("potentialUsers", equalTo(List.of()))
+ .body("potentialGroups", hasItems(potentialGroups));
+
+ claim(taskId, user, group);
+ start(taskId, user, group);
+ complete(taskId, user, group);
+
+ isProcessCompleted(processId, pid);
+ }
+
private void nominate(String taskId, String user, String status, String[] nominatedUsers) {
given()
.contentType(ContentType.JSON)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org