From eb75e55564352a269abc4c74b4c11dd6e8926bcf Mon Sep 17 00:00:00 2001 From: Stijn Vlaes Date: Tue, 5 Aug 2025 13:28:15 +0200 Subject: [PATCH 1/3] feat(engine): variable and process definition queries for external tasks - adds functionality to filter external tasks based on process variables - adds functionality to filter external tasks based on process definition key - adds functionality to filter external tasks based on process definition name related to https://github.com/camunda/camunda-bpm-platform/issues/5334 --- .../externaltask/ExternalTaskQuery.java | 92 +++- .../engine/impl/ExternalTaskQueryImpl.java | 190 ++++++- .../impl/mapping/entity/ExternalTask.xml | 36 ++ .../externaltask/ExternalTaskQueryTest.java | 497 +++++++++++++++++- .../oneExternalTaskProcess.bpmn20.xml | 2 +- 5 files changed, 779 insertions(+), 38 deletions(-) diff --git a/engine/src/main/java/org/camunda/bpm/engine/externaltask/ExternalTaskQuery.java b/engine/src/main/java/org/camunda/bpm/engine/externaltask/ExternalTaskQuery.java index 3bba6f68540..87b0ec920f9 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/externaltask/ExternalTaskQuery.java +++ b/engine/src/main/java/org/camunda/bpm/engine/externaltask/ExternalTaskQuery.java @@ -16,11 +16,12 @@ */ package org.camunda.bpm.engine.externaltask; +import org.camunda.bpm.engine.query.Query; + +import java.io.Serializable; import java.util.Date; import java.util.Set; -import org.camunda.bpm.engine.query.Query; - /** * @author Thorben Lindhauer * @author Christopher Zell @@ -84,11 +85,36 @@ public interface ExternalTaskQuery extends Query variables = new ArrayList<>(); protected Boolean retriesLeft; protected String[] tenantIds; @@ -104,12 +118,12 @@ public ExternalTaskQuery topicName(String topicName) { } public ExternalTaskQuery locked() { - this.locked = Boolean.TRUE; + this.locked = TRUE; return this; } public ExternalTaskQuery notLocked() { - this.notLocked = Boolean.TRUE; + this.notLocked = TRUE; return this; } @@ -131,12 +145,36 @@ public ExternalTaskQuery processInstanceIdIn(String... processInstanceIdIn) { return this; } + @Override + public ExternalTaskQuery processDefinitionKey(String processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + return this; + } + + @Override + public ExternalTaskQuery processDefinitionKeyIn(String... processDefinitionKeys) { + this.processDefinitionKeys = processDefinitionKeys; + return this; + } + public ExternalTaskQuery processDefinitionId(String processDefinitionId) { ensureNotNull("processDefinitionId", processDefinitionId); this.processDefinitionId = processDefinitionId; return this; } + @Override + public ExternalTaskQuery processDefinitionName(String processDefinitionName) { + this.processDefinitionName = processDefinitionName; + return this; + } + + @Override + public ExternalTaskQuery processDefinitionNameLike(String processDefinitionName) { + this.processDefinitionNameLike = processDefinitionName; + return this; + } + public ExternalTaskQuery activityId(String activityId) { ensureNotNull("activityId", activityId); this.activityId = activityId; @@ -160,6 +198,108 @@ public ExternalTaskQuery priorityLowerThanOrEquals(long priority) { return this; } + @Override + public ExternalTaskQuery processVariableValueEquals(String variableName, Object variableValue) { + addVariable(variableName, variableValue, QueryOperator.EQUALS); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueNotEquals(String variableName, Object variableValue) { + addVariable(variableName, variableValue, QueryOperator.NOT_EQUALS); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueLike(String variableName, String variableValue) { + addVariable(variableName, variableValue, QueryOperator.LIKE); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueNotLike(String variableName, String variableValue) { + addVariable(variableName, variableValue, QueryOperator.NOT_LIKE); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueGreaterThan(String variableName, Object variableValue) { + addVariable(variableName, variableValue, QueryOperator.GREATER_THAN); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueGreaterThanOrEquals(String variableName, Object variableValue) { + addVariable(variableName, variableValue, QueryOperator.GREATER_THAN_OR_EQUAL); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueLessThan(String variableName, Object variableValue) { + addVariable(variableName, variableValue, QueryOperator.LESS_THAN); + return this; + } + + @Override + public ExternalTaskQuery processVariableValueLessThanOrEquals(String variableName, Object variableValue) { + addVariable(variableName, variableValue, QueryOperator.LESS_THAN_OR_EQUAL); + return this; + } + + @Override + public ExternalTaskQuery matchVariableNamesIgnoreCase() { + this.variableNamesIgnoreCase = true; + for (QueryVariableValue variable : this.variables) { + variable.setVariableNameIgnoreCase(true); + } + return this; + } + + @Override + public ExternalTaskQuery matchVariableValuesIgnoreCase() { + this.variableValuesIgnoreCase = true; + for (QueryVariableValue variable : this.variables) { + variable.setVariableValueIgnoreCase(true); + } + return this; + } + + public void addVariable(String name, Object value, QueryOperator operator) { + ensureNotNull("name", name); + + if(value == null || isBoolean(value)) { + // Null-values and booleans can only be used in EQUALS and NOT_EQUALS + switch(operator) { + case GREATER_THAN: + throw new ProcessEngineException("Booleans and null cannot be used in 'greater than' condition"); + case LESS_THAN: + throw new ProcessEngineException("Booleans and null cannot be used in 'less than' condition"); + case GREATER_THAN_OR_EQUAL: + throw new ProcessEngineException("Booleans and null cannot be used in 'greater than or equal' condition"); + case LESS_THAN_OR_EQUAL: + throw new ProcessEngineException("Booleans and null cannot be used in 'less than or equal' condition"); + case LIKE: + throw new ProcessEngineException("Booleans and null cannot be used in 'like' condition"); + case NOT_LIKE: + throw new ProcessEngineException("Booleans and null cannot be used in 'not like' condition"); + default: + break; + } + } + boolean shouldMatchVariableValuesIgnoreCase = TRUE.equals(variableValuesIgnoreCase) && value != null && String.class.isAssignableFrom(value.getClass()); + addVariable(new QueryVariableValue(name, value, operator, false, TRUE.equals(variableNamesIgnoreCase), shouldMatchVariableValuesIgnoreCase)); + } + + protected void addVariable(QueryVariableValue queryVariableValue) { + variables.add(queryVariableValue); + } + + private boolean isBoolean(Object value) { + if (value == null) { + return false; + } + return Boolean.class.isAssignableFrom(value.getClass()) || boolean.class.isAssignableFrom(value.getClass()); + } public ExternalTaskQuery suspended() { this.suspensionState = SuspensionState.SUSPENDED; @@ -172,7 +312,7 @@ public ExternalTaskQuery active() { } public ExternalTaskQuery withRetriesLeft() { - this.retriesLeft = Boolean.TRUE; + this.retriesLeft = TRUE; return this; } @@ -229,6 +369,7 @@ public ExternalTaskQuery orderByCreateTime() { @Override public long executeCount(CommandContext commandContext) { + ensureVariablesInitialized(); checkQueryOk(); return commandContext .getExternalTaskManager() @@ -237,6 +378,7 @@ public long executeCount(CommandContext commandContext) { @Override public List executeList(CommandContext commandContext, Page page) { + ensureVariablesInitialized(); checkQueryOk(); return commandContext .getExternalTaskManager() @@ -244,6 +386,7 @@ public List executeList(CommandContext commandContext, Page page) } public List executeIdsList(CommandContext commandContext) { + ensureVariablesInitialized(); checkQueryOk(); return commandContext .getExternalTaskManager() @@ -294,10 +437,26 @@ public String getProcessInstanceId() { return processInstanceId; } + public String getProcessDefinitionKey() { + return processDefinitionKey; + } + + public String[] getProcessDefinitionKeys() { + return processDefinitionKeys; + } + public String getProcessDefinitionId() { return processDefinitionId; } + public String getProcessDefinitionName() { + return processDefinitionName; + } + + public String getProcessDefinitionNameLike() { + return processDefinitionNameLike; + } + public String getActivityId() { return activityId; } @@ -314,4 +473,17 @@ public Date getNow() { return ClockUtil.getCurrentTime(); } + protected void ensureVariablesInitialized() { + ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration(); + VariableSerializers variableSerializers = processEngineConfiguration.getVariableSerializers(); + String dbType = processEngineConfiguration.getDatabaseType(); + for(QueryVariableValue var : variables) { + var.initialize(variableSerializers, dbType); + } + } + + public List getVariables() { + return variables; + } + } diff --git a/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/ExternalTask.xml b/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/ExternalTask.xml index af480769d97..fb15a1b2ba5 100644 --- a/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/ExternalTask.xml +++ b/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/ExternalTask.xml @@ -394,6 +394,22 @@ and RES.PROC_DEF_ID_ = #{processDefinitionId} + + and PD.KEY_ = #{processDefinitionKey} + + + and PD.KEY_ in + + #{item} + + + + and PD.NAME_ = #{processDefinitionName} + + + and PD.NAME_ like #{processDefinitionNameLike} ESCAPE ${escapeChar} + and RES.ACT_ID_ = #{activityId} @@ -433,6 +449,26 @@ #{tenantId} + + + and EXISTS ( + select + ID_ + from + ${prefix}ACT_RU_VARIABLE + WHERE + + + + and TASK_ID_ is null + and RES.PROC_INST_ID_ = PROC_INST_ID_ + + + and + + + ) + diff --git a/engine/src/test/java/org/camunda/bpm/engine/test/api/externaltask/ExternalTaskQueryTest.java b/engine/src/test/java/org/camunda/bpm/engine/test/api/externaltask/ExternalTaskQueryTest.java index a09ed4cf575..466b4bdefe2 100644 --- a/engine/src/test/java/org/camunda/bpm/engine/test/api/externaltask/ExternalTaskQueryTest.java +++ b/engine/src/test/java/org/camunda/bpm/engine/test/api/externaltask/ExternalTaskQueryTest.java @@ -16,49 +16,31 @@ */ package org.camunda.bpm.engine.test.api.externaltask; -import static org.assertj.core.api.Assertions.assertThat; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.externalTaskById; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.externalTaskByLockExpirationTime; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.externalTaskByProcessDefinitionId; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.externalTaskByProcessDefinitionKey; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.externalTaskByProcessInstanceId; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.inverted; -import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.verifySorting; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.camunda.bpm.engine.ProcessEngineException; import org.camunda.bpm.engine.exception.NullValueException; import org.camunda.bpm.engine.externaltask.ExternalTask; import org.camunda.bpm.engine.externaltask.ExternalTaskQuery; import org.camunda.bpm.engine.externaltask.LockedExternalTask; -import org.camunda.bpm.engine.impl.db.sql.DbSqlSessionFactory; -import org.camunda.bpm.engine.impl.test.RequiredDatabase; import org.camunda.bpm.engine.impl.util.ClockUtil; import org.camunda.bpm.engine.repository.ProcessDefinition; import org.camunda.bpm.engine.runtime.ActivityInstance; import org.camunda.bpm.engine.runtime.ProcessInstance; import org.camunda.bpm.engine.test.Deployment; import org.camunda.bpm.engine.test.util.PluggableProcessEngineTest; +import org.camunda.bpm.engine.variable.Variables; import org.camunda.bpm.model.bpmn.Bpmn; import org.camunda.bpm.model.bpmn.BpmnModelInstance; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.camunda.bpm.engine.test.api.runtime.TestOrderingUtil.*; +import static org.junit.Assert.*; + /** * @author Thorben Lindhauer * @@ -68,6 +50,10 @@ public class ExternalTaskQueryTest extends PluggableProcessEngineTest { protected static final String WORKER_ID = "aWorkerId"; protected static final String TOPIC_NAME = "externalTaskTopic"; protected static final String ERROR_MESSAGE = "error"; + // The range of Oracle's NUMBER field is limited to ~10e+125 + // which is below Double.MAX_VALUE, so we only test with the following + // max value + protected static final double MAX_DOUBLE_VALUE = 10E+124; @Before public void setUp() throws Exception { @@ -689,6 +675,465 @@ public void shouldCheckPresenceOfVersionTag() { assertThat(task.getProcessDefinitionVersionTag()).isEqualTo("1.2.3.4"); } + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessDefinitionKey() throws Exception { + assertEquals(0, externalTaskService.createExternalTaskQuery().processDefinitionKey("oneExternalTaskProcess").count()); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess"); + assertEquals(1, externalTaskService.createExternalTaskQuery().processDefinitionKey("oneExternalTaskProcess").count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessDefinitionKeyIn() throws Exception { + assertEquals(0, externalTaskService.createExternalTaskQuery().processDefinitionKeyIn("oneExternalTaskProcess").count()); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess"); + assertEquals(1, externalTaskService.createExternalTaskQuery().processDefinitionKeyIn("oneExternalTaskProcess").count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessDefinitionName() throws Exception { + assertEquals(0, externalTaskService.createExternalTaskQuery().processDefinitionName("One external task process").count()); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess"); + assertEquals(1, externalTaskService.createExternalTaskQuery().processDefinitionName("One external task process").count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void processDefinitionNameLike() throws Exception { + assertEquals(0, externalTaskService.createExternalTaskQuery().processDefinitionNameLike("One external task proc%").count()); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess"); + assertEquals(1, externalTaskService.createExternalTaskQuery().processDefinitionNameLike("One external task proc%").count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueEquals() throws Exception { + Map variables = new HashMap<>(); + variables.put("longVar", 928374L); + variables.put("shortVar", (short) 123); + variables.put("integerVar", 1234); + variables.put("stringVar", "stringValue"); + variables.put("booleanVar", true); + Date date = Calendar.getInstance().getTime(); + variables.put("dateVar", date); + variables.put("nullVar", null); + + // Start process-instance with all types of variables + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + // Test query matches + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("longVar", 928374L).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("shortVar", (short) 123).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("integerVar", 1234).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("stringVar", "stringValue").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("booleanVar", true).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("dateVar", date).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("nullVar", null).count()); + + // Test query for other values on existing variables + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("longVar", 999L).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("shortVar", (short) 999).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("integerVar", 999).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("stringVar", "999").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("booleanVar", false).count()); + Calendar otherDate = Calendar.getInstance(); + otherDate.add(Calendar.YEAR, 1); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("dateVar", otherDate.getTime()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("nullVar", "999").count()); + + // Test querying for task variables not equals + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("longVar", 999L).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("shortVar", (short) 999).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("integerVar", 999).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("stringVar", "999").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("booleanVar", false).count()); + + // and query for the existing variable with NOT should result in nothing found: + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("longVar", 928374L).count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableNameEqualsIgnoreCase() throws Exception { + String variableName = "someVariable"; + String variableValue = "someCamelCaseValue"; + Map variables = new HashMap<>(); + variables.put(variableName, variableValue); + + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + // query for case-insensitive variable name should only return a result if case-insensitive search is used + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableNamesIgnoreCase().processVariableValueEquals(variableName.toLowerCase(), variableValue).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals(variableName.toLowerCase(), variableValue).count()); + + // query should treat all variables case-insensitively, even when flag is set after variable + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals(variableName.toLowerCase(), variableValue).matchVariableNamesIgnoreCase().count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueEqualsIgnoreCase() throws Exception { + String variableName = "someVariable"; + String variableValue = "someCamelCaseValue"; + Map variables = new HashMap<>(); + variables.put(variableName, variableValue); + + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + // query for existing variable should return one result + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals(variableName, variableValue).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueEquals(variableName, variableValue.toLowerCase()).count()); + + // query for non existing variable should return zero results + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("nonExistentVariable", variableValue.toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueEquals("nonExistentVariable", variableValue.toLowerCase()).count()); + + // query for existing variable with different value should return zero results + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals(variableName, "nonExistentValue").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueEquals(variableName, "nonExistentValue".toLowerCase()).count()); + + // query for case-insensitive variable value should only return a result when case-insensitive search is used + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals(variableName, variableValue.toLowerCase()).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueEquals(variableName, variableValue.toLowerCase()).count()); + + // query for case-insensitive variable with not equals operator should only return a result when case-sensitive search is used + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals(variableName, variableValue.toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotEquals(variableName, variableValue.toLowerCase()).count()); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueLike() throws Exception { + Map variables = new HashMap<>(); + variables.put("stringVar", "stringValue"); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "stringVal%").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "%ngValue").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "%ngVal%").count()); + + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "stringVar%").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "%ngVar").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "%ngVar%").count()); + + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "stringVal").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLike("nonExistingVar", "string%").count()); + + // test with null value + try { + externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", null).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueLikeIgnoreCase() throws Exception { + + Map variables = new HashMap<>(); + variables.put("stringVar", "stringValue"); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLike("stringVar", "stringVal%".toLowerCase()).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "stringVal%".toLowerCase()).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "%ngValue".toLowerCase()).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "%ngVal%".toLowerCase()).count()); + + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "stringVar%".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "%ngVar".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "%ngVar%".toLowerCase()).count()); + + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", "stringVal".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("nonExistingVar", "stringVal%".toLowerCase()).count()); + + // test with null value + try { + externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueLike("stringVar", null).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueNotLike() throws Exception { + Map variables = new HashMap<>(); + variables.put("stringVar", "stringValue"); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "stringVal%").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "%ngValue").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "%ngVal%").count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "stringVar%").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "%ngVar").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "%ngVar%").count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "stringVal").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("nonExistingVar", "string%").count()); + + // test with null value + assertThatThrownBy(() -> externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", null).count()) + .isInstanceOf(ProcessEngineException.class); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueNotLikeIgnoreCase() throws Exception { + Map variables = new HashMap<>(); + variables.put("stringVar", "stringValue"); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueNotLike("stringVar", "stringVal%".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "stringVal%".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "%ngValue".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "%ngVal%".toLowerCase()).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "stringVar%".toLowerCase()).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "%ngVar".toLowerCase()).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "%ngVar%".toLowerCase()).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", "stringVal".toLowerCase()).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("nonExistingVar", "stringVal%".toLowerCase()).count()); + + // test with null value + assertThatThrownBy(() -> externalTaskService.createExternalTaskQuery().matchVariableValuesIgnoreCase().processVariableValueNotLike("stringVar", null).count()) + .isInstanceOf(ProcessEngineException.class); + } + + @Deployment(resources="org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueCompare() throws Exception { + + Map variables = new HashMap<>(); + variables.put("numericVar", 928374); + Date date = new GregorianCalendar(2014, 2, 2, 2, 2, 2).getTime(); + variables.put("dateVar", date); + variables.put("stringVar", "ab"); + variables.put("nullVar", null); + + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", variables); + + // test compare methods with numeric values + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("numericVar", 928373).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("numericVar", 928374).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("numericVar", 928375).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("numericVar", 928373).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("numericVar", 928374).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("numericVar", 928375).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("numericVar", 928375).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("numericVar", 928374).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("numericVar", 928373).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("numericVar", 928375).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("numericVar", 928374).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("numericVar", 928373).count()); + + // test compare methods with date values + Date before = new GregorianCalendar(2014, 2, 2, 2, 2, 1).getTime(); + Date after = new GregorianCalendar(2014, 2, 2, 2, 2, 3).getTime(); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("dateVar", before).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("dateVar", date).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("dateVar", after).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("dateVar", before).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("dateVar", date).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("dateVar", after).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("dateVar", after).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("dateVar", date).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("dateVar", before).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("dateVar", after).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("dateVar", date).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("dateVar", before).count()); + + //test with string values + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("stringVar", "aa").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("stringVar", "ab").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("stringVar", "ba").count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("stringVar", "aa").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("stringVar", "ab").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("stringVar", "ba").count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("stringVar", "ba").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("stringVar", "ab").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("stringVar", "aa").count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("stringVar", "ba").count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("stringVar", "ab").count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("stringVar", "aa").count()); + + // test with null value + try { + externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("nullVar", null).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + try { + externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("nullVar", null).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + try { + externalTaskService.createExternalTaskQuery().processVariableValueLessThan("nullVar", null).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + try { + externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("nullVar", null).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + + // test with boolean value + try { + externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("nullVar", true).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + try { + externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("nullVar", false).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + try { + externalTaskService.createExternalTaskQuery().processVariableValueLessThan("nullVar", true).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + try { + externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("nullVar", false).count(); + fail("expected exception"); + } catch (final ProcessEngineException e) {/*OK*/} + + // test non existing variable + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("nonExisting", 123).count()); + } + + @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueEqualsNumber() throws Exception { + // long + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 123L)); + + // non-matching long + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 12345L)); + + // short + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", (short) 123)); + + // double + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 123.0d)); + + // integer + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 123)); + + // untyped null (should not match) + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", null)); + + // typed null (should not match) + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", Variables.longValue(null))); + + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", "123")); + + assertEquals(4, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(123)).count()); + assertEquals(4, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(123L)).count()); + assertEquals(4, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(123.0d)).count()); + assertEquals(4, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue((short) 123)).count()); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(null)).count()); + } + + @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testProcessVariableValueNumberComparison() throws Exception { + // long + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 123L)); + + // non-matching long + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 12345L)); + + // short + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", (short) 123)); + + // double + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 123.0d)); + + // integer + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 123)); + + // untyped null + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", null)); + + // typed null + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", Variables.longValue(null))); + + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", "123")); + + assertEquals(4, externalTaskService.createExternalTaskQuery().processVariableValueNotEquals("var", Variables.numberValue(123)).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThan("var", Variables.numberValue(123)).count()); + assertEquals(5, externalTaskService.createExternalTaskQuery().processVariableValueGreaterThanOrEquals("var", Variables.numberValue(123)).count()); + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueLessThan("var", Variables.numberValue(123)).count()); + assertEquals(4, externalTaskService.createExternalTaskQuery().processVariableValueLessThanOrEquals("var", Variables.numberValue(123)).count()); + } + + @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testVariableEqualsNumberMax() throws Exception { + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", MAX_DOUBLE_VALUE)); + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", Long.MAX_VALUE)); + + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(MAX_DOUBLE_VALUE)).count()); + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(Long.MAX_VALUE)).count()); + } + + @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testVariableEqualsNumberLongValueOverflow() throws Exception { + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", MAX_DOUBLE_VALUE)); + + // this results in an overflow + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", (long) MAX_DOUBLE_VALUE)); + + // the query should not find the long variable + assertEquals(1, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(MAX_DOUBLE_VALUE)).count()); + } + + @Deployment(resources = "org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml") + @Test + public void testVariableEqualsNumberNonIntegerDoubleShouldNotMatchInteger() throws Exception { + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Variables.createVariables().putValue("var", 42).putValue("var2", 52.4d)); + + // querying by 42.4 should not match the integer variable 42 + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(42.4d)).count()); + + runtimeService.startProcessInstanceByKey("oneExternalTaskProcess", + Collections.singletonMap("var", 42.4d)); + + // querying by 52 should not find the double variable 52.4 + assertEquals(0, externalTaskService.createExternalTaskQuery().processVariableValueEquals("var", Variables.numberValue(52)).count()); + } + protected List startInstancesByKey(String processDefinitionKey, int number) { List processInstances = new ArrayList<>(); for (int i = 0; i < number; i++) { diff --git a/engine/src/test/resources/org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml b/engine/src/test/resources/org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml index fe436b450a4..b5596542d16 100644 --- a/engine/src/test/resources/org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml +++ b/engine/src/test/resources/org/camunda/bpm/engine/test/api/externaltask/oneExternalTaskProcess.bpmn20.xml @@ -4,7 +4,7 @@ xmlns:camunda="http://camunda.org/schema/1.0/bpmn" targetNamespace="Examples"> - + From d3945d31d4125241116245e4976c7bb67c2113e7 Mon Sep 17 00:00:00 2001 From: Stijn Vlaes Date: Tue, 5 Aug 2025 14:33:52 +0200 Subject: [PATCH 2/3] feat(rest): variable and process definition queries for external tasks - adds functionality to the rest external task query dto based on process variables - adds functionality to the rest external task query dto based on process definition key - adds functionality to the rest external task query dto based on process definition name related to https://github.com/camunda/camunda-bpm-platform/issues/5334 --- .../commons/external-task-query-params.ftl | 70 +++- .../externaltask/ExternalTaskQueryDto.ftl | 58 +++ .../externaltask/ExternalTaskQueryDto.java | 97 ++++- .../ExternalTaskRestServiceQueryTest.java | 362 +++++++++++++++++- 4 files changed, 568 insertions(+), 19 deletions(-) diff --git a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/external-task-query-params.ftl b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/external-task-query-params.ftl index 282a1dbd7d5..f2629782e76 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/external-task-query-params.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/external-task-query-params.ftl @@ -136,6 +136,72 @@ location = "query" type = "integer" format = "int64" - last = last desc = "Only include jobs with a priority lower than or equal to the given value. - Value must be a valid `long` value." /> \ No newline at end of file + Value must be a valid `long` value." /> + + <@lib.parameter + name = "processDefinitionKey" + location = "query" + type = "string" + desc = "Restrict to tasks that belong to a process definition with the given key." /> + + <@lib.parameter + name = "processDefinitionKeyIn" + location = "query" + type = "string" + desc = "Restrict to tasks that belong to a process definition with one of the given keys. The + keys need to be in a comma-separated list." /> + + <@lib.parameter + name = "processDefinitionName" + location = "query" + type = "string" + desc = "Restrict to tasks that belong to a process definition with the given name." /> + + <@lib.parameter + name = "processDefinitionNameLike" + location = "query" + type = "string" + desc = "Restrict to tasks that have a process definition name that has the parameter value as + a substring." /> + + <@lib.parameter + name = "variableNamesIgnoreCase" + location = "query" + type = "boolean" + defaultValue = "false" + desc = "Match all variable names in this query case-insensitively. If set + `variableName` and `variablename` are treated as equal." /> + + <@lib.parameter + name = "variableValuesIgnoreCase" + location = "query" + type = "boolean" + defaultValue = "false" + desc = "Match all variable values in this query case-insensitively. If set + `variableValue` and `variablevalue` are treated as equal." /> + + <@lib.parameter + name = "processVariables" + location = "query" + type = "string" + last = last + desc = "Only include tasks that belong to process instances that have variables with certain + values. Variable filtering expressions are comma-separated and are structured as + follows: + + A valid parameter value has the form `key_operator_value`. `key` is the variable name, + `operator` is the comparison operator to be used and `value` the variable value. + + **Note**: Values are always treated as String objects on server side. + + Valid `operator` values are: + `eq` - equal to; + `neq` - not equal to; + `gt` - greater than; + `gteq` - greater than or equal to; + `lt` - lower than; + `lteq` - lower than or equal to; + `like`; + `notLike`. + `key` and `value` may not contain underscore or comma characters." /> \ No newline at end of file diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/camunda/bpm/engine/rest/dto/runtime/externaltask/ExternalTaskQueryDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/camunda/bpm/engine/rest/dto/runtime/externaltask/ExternalTaskQueryDto.ftl index 126845721e4..af4e0cde716 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/models/org/camunda/bpm/engine/rest/dto/runtime/externaltask/ExternalTaskQueryDto.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/camunda/bpm/engine/rest/dto/runtime/externaltask/ExternalTaskQueryDto.ftl @@ -127,6 +127,64 @@ desc = "Only include jobs with a priority lower than or equal to the given value. Value must be a valid `long` value." /> + <@lib.property + name = "processDefinitionKey" + type = "string" + desc = "Restrict to tasks that belong to a process definition with the given key." /> + + <@lib.property + name = "processDefinitionKeyIn" + type = "array" + itemType = "string" + desc = "Restrict to tasks that belong to a process definition with one of the given keys. The + keys need to be in a comma-separated list." /> + + <@lib.property + name = "processDefinitionName" + type = "string" + desc = "Restrict to tasks that belong to a process definition with the given name." /> + + <@lib.property + name = "processDefinitionNameLike" + type = "string" + desc = "Restrict to tasks that have a process definition name that has the parameter value as + a substring." /> + + <@lib.property + name = "variableNamesIgnoreCase" + type = "boolean" + defaultValue = "false" + desc = "Match all variable names in this query case-insensitively. If set + `variableName` and `variablename` are treated as equal." /> + + <@lib.property + name = "variableValuesIgnoreCase" + type = "boolean" + defaultValue = "false" + desc = "Match all variable values in this query case-insensitively. If set + `variableValue` and `variablevalue` are treated as equal." /> + + <@lib.property + name = "processVariables" + type = "array" + dto = "VariableQueryParameterDto" + desc = "A JSON array to only include tasks that belong to a process instance with variables + with certain values. The array consists of JSON objects with three properties + `name`, `operator` and `value`. `name` is the variable name, `operator` is the + comparison operator to be used and `value` the variable value. `value` may be of + type `String`, `Number` or `Boolean`. + + Valid `operator` values are: + `eq` - equal to; + `neq` - not equal to; + `gt` - greater than; + `gteq` - greater than or equal to; + `lt` - lower than; + `lteq` - lower than or equal to; + `like`; + `notLike`. + `key` and `value` may not contain underscore or comma characters." /> + "sorting": { "type": "array", "nullable": true, diff --git a/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/externaltask/ExternalTaskQueryDto.java b/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/externaltask/ExternalTaskQueryDto.java index e13cf2cd63f..d0c80a3bae4 100644 --- a/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/externaltask/ExternalTaskQueryDto.java +++ b/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/externaltask/ExternalTaskQueryDto.java @@ -23,15 +23,15 @@ import java.util.Set; import java.util.function.Consumer; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; + import org.camunda.bpm.engine.ProcessEngine; import org.camunda.bpm.engine.externaltask.ExternalTaskQuery; import org.camunda.bpm.engine.rest.dto.AbstractQueryDto; import org.camunda.bpm.engine.rest.dto.CamundaQueryParam; -import org.camunda.bpm.engine.rest.dto.converter.BooleanConverter; -import org.camunda.bpm.engine.rest.dto.converter.DateConverter; -import org.camunda.bpm.engine.rest.dto.converter.LongConverter; -import org.camunda.bpm.engine.rest.dto.converter.StringListConverter; -import org.camunda.bpm.engine.rest.dto.converter.StringSetConverter; +import org.camunda.bpm.engine.rest.dto.VariableQueryParameterDto; +import org.camunda.bpm.engine.rest.dto.converter.*; +import org.camunda.bpm.engine.rest.exception.InvalidRequestException; /** * @author Thorben Lindhauer @@ -62,7 +62,11 @@ public class ExternalTaskQueryDto extends AbstractQueryDto { protected String executionId; protected String processInstanceId; protected List processInstanceIdIn; + protected String processDefinitionKey; + protected String[] processDefinitionKeyIn; protected String processDefinitionId; + protected String processDefinitionName; + protected String processDefinitionNameLike; protected Boolean active; protected Boolean suspended; protected Boolean withRetriesLeft; @@ -71,6 +75,10 @@ public class ExternalTaskQueryDto extends AbstractQueryDto { protected List tenantIds; protected Long priorityHigherThanOrEquals; protected Long priorityLowerThanOrEquals; + protected Boolean variableNamesIgnoreCase; + protected Boolean variableValuesIgnoreCase; + + private List processVariables; public ExternalTaskQueryDto() { } @@ -143,11 +151,31 @@ public String getProcessDefinitionId() { return processDefinitionId; } + @CamundaQueryParam("processDefinitionKey") + public void setProcessDefinitionKey(String processDefinitionKey) { + this.processDefinitionKey = processDefinitionKey; + } + + @CamundaQueryParam(value = "processDefinitionKeyIn", converter = StringArrayConverter.class) + public void setProcessDefinitionKeyIn(String[] processDefinitionKeyIn) { + this.processDefinitionKeyIn = processDefinitionKeyIn; + } + @CamundaQueryParam("processDefinitionId") public void setProcessDefinitionId(String processDefinitionId) { this.processDefinitionId = processDefinitionId; } + @CamundaQueryParam("processDefinitionName") + public void setProcessDefinitionName(String processDefinitionName) { + this.processDefinitionName = processDefinitionName; + } + + @CamundaQueryParam("processDefinitionNameLike") + public void setProcessDefinitionNameLike(String processDefinitionNameLike) { + this.processDefinitionNameLike = processDefinitionNameLike; + } + @CamundaQueryParam(value = "active", converter = BooleanConverter.class) public void setActive(Boolean active) { this.active = active; @@ -182,6 +210,21 @@ public void setPriorityHigherThanOrEquals(Long priorityHigherThanOrEquals) { this.priorityHigherThanOrEquals = priorityHigherThanOrEquals; } + @CamundaQueryParam(value = "variableNamesIgnoreCase", converter = BooleanConverter.class) + public void setVariableNamesIgnoreCase(Boolean variableNamesCaseInsensitive) { + this.variableNamesIgnoreCase = variableNamesCaseInsensitive; + } + + @CamundaQueryParam(value ="variableValuesIgnoreCase", converter = BooleanConverter.class) + public void setVariableValuesIgnoreCase(Boolean variableValuesCaseInsensitive) { + this.variableValuesIgnoreCase = variableValuesCaseInsensitive; + } + + @CamundaQueryParam(value = "processVariables", converter = VariableListConverter.class) + public void setProcessVariables(List processVariables) { + this.processVariables = processVariables; + } + @CamundaQueryParam(value="priorityLowerThanOrEquals", converter = LongConverter.class) public void setPriorityLowerThanOrEquals(Long priorityLowerThanOrEquals) { this.priorityLowerThanOrEquals = priorityLowerThanOrEquals; @@ -235,9 +278,21 @@ protected void applyFilters(ExternalTaskQuery query) { if (processInstanceIdIn != null && !processInstanceIdIn.isEmpty()) { query.processInstanceIdIn(processInstanceIdIn.toArray(new String[0])); } + if (processDefinitionKey != null) { + query.processDefinitionKey(processDefinitionKey); + } + if (processDefinitionKeyIn != null && processDefinitionKeyIn.length > 0) { + query.processDefinitionKeyIn(processDefinitionKeyIn); + } if (processDefinitionId != null) { query.processDefinitionId(processDefinitionId); } + if (processDefinitionName != null) { + query.processDefinitionName(processDefinitionName); + } + if (processDefinitionNameLike != null) { + query.processDefinitionNameLike(processDefinitionNameLike); + } if (active != null && active) { query.active(); } @@ -256,6 +311,38 @@ protected void applyFilters(ExternalTaskQuery query) { if (noRetriesLeft != null && noRetriesLeft) { query.noRetriesLeft(); } + if(variableValuesIgnoreCase != null && variableValuesIgnoreCase) { + query.matchVariableValuesIgnoreCase(); + } + if(variableNamesIgnoreCase != null && variableNamesIgnoreCase) { + query.matchVariableNamesIgnoreCase(); + } + if (processVariables != null) { + for (VariableQueryParameterDto variableQueryParam : processVariables) { + String variableName = variableQueryParam.getName(); + String op = variableQueryParam.getOperator(); + Object variableValue = variableQueryParam.resolveValue(objectMapper); + if (op.equals(VariableQueryParameterDto.EQUALS_OPERATOR_NAME)) { + query.processVariableValueEquals(variableName, variableValue); + } else if (op.equals(VariableQueryParameterDto.NOT_EQUALS_OPERATOR_NAME)) { + query.processVariableValueNotEquals(variableName, variableValue); + } else if (op.equals(VariableQueryParameterDto.GREATER_THAN_OPERATOR_NAME)) { + query.processVariableValueGreaterThan(variableName, variableValue); + } else if (op.equals(VariableQueryParameterDto.GREATER_THAN_OR_EQUALS_OPERATOR_NAME)) { + query.processVariableValueGreaterThanOrEquals(variableName, variableValue); + } else if (op.equals(VariableQueryParameterDto.LESS_THAN_OPERATOR_NAME)) { + query.processVariableValueLessThan(variableName, variableValue); + } else if (op.equals(VariableQueryParameterDto.LESS_THAN_OR_EQUALS_OPERATOR_NAME)) { + query.processVariableValueLessThanOrEquals(variableName, variableValue); + } else if (op.equals(VariableQueryParameterDto.LIKE_OPERATOR_NAME)) { + query.processVariableValueLike(variableName, String.valueOf(variableValue)); + } else if (op.equals(VariableQueryParameterDto.NOT_LIKE_OPERATOR_NAME)) { + query.processVariableValueNotLike(variableName, String.valueOf(variableValue)); + } else { + throw new InvalidRequestException(Response.Status.BAD_REQUEST, "Invalid process variable comparator specified: " + op); + } + } + } if (workerId != null) { query.workerId(workerId); } diff --git a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java index 46f2dfa670f..f0fdaca6d3c 100644 --- a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java @@ -21,17 +21,10 @@ import static org.camunda.bpm.engine.rest.util.DateTimeUtils.withTimezone; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.reset; + +import java.util.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response.Status; @@ -67,6 +60,9 @@ public class ExternalTaskRestServiceQueryTest extends AbstractRestServiceTest { public static final long EXTERNAL_TASK_LOW_BOUND_PRIORITY = 3L; public static final long EXTERNAL_TASK_HIGH_BOUND_PRIORITY = 4L; + private static final String SAMPLE_VAR_NAME = "varName"; + private static final String SAMPLE_VAR_VALUE = "varValue"; + protected ExternalTaskQuery mockQuery; @Before @@ -183,6 +179,10 @@ public void testCompleteGETQuery() { parameters.put("processInstanceIdIn", "aProcessInstanceId,anotherProcessInstanceId"); parameters.put("processDefinitionId", "someProcessDefinitionId"); parameters.put("processDefinitionVersionTag", "someProcessDefinitionVersionTag"); + parameters.put("processDefinitionKey", "procDefKey"); + parameters.put("processDefinitionKeyIn", "procDefKey1,procDefKey2"); + parameters.put("processDefinitionName", "procDefName"); + parameters.put("processDefinitionNameLike", "procDefName%"); parameters.put("active", "true"); parameters.put("suspended", "true"); parameters.put("withRetriesLeft", "true"); @@ -208,7 +208,10 @@ public void testCompleteGETQuery() { verify(mockQuery).processInstanceId("someProcessInstanceId"); verify(mockQuery).processInstanceIdIn("aProcessInstanceId", "anotherProcessInstanceId"); verify(mockQuery).processDefinitionId("someProcessDefinitionId"); - verify(mockQuery).processDefinitionId("someProcessDefinitionId"); + verify(mockQuery).processDefinitionKey("procDefKey"); + verify(mockQuery).processDefinitionKeyIn("procDefKey2", "procDefKey3"); + verify(mockQuery).processDefinitionName("procDefName"); + verify(mockQuery).processDefinitionNameLike("procDefName%"); verify(mockQuery).active(); verify(mockQuery).suspended(); verify(mockQuery).withRetriesLeft(); @@ -670,6 +673,341 @@ public void testQueryByExternalTaskIdListPost() { assertThat(returnedId2).isEqualTo(MockProvider.EXTERNAL_TASK_ANOTHER_ID); } + @Test + public void testProcessVariableParameters() { + // equals + String variableName = "varName"; + String variableValue = "varValue"; + String queryValue = variableName + "_eq_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueEquals(variableName, variableValue); + reset(mockQuery); + + //equals case-insensitive + queryValue = variableName + "_eq_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .queryParam("variableValuesIgnoreCase", true) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueEquals(variableName, variableValue); + reset(mockQuery); + + given() + .queryParam("processVariables", queryValue) + .queryParam("variableNamesIgnoreCase", true) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableNamesIgnoreCase(); + verify(mockQuery).processVariableValueEquals(variableName, variableValue); + reset(mockQuery); + + given() + .queryParam("processVariables", queryValue) + .queryParam("variableNamesIgnoreCase", true) + .queryParam("variableValuesIgnoreCase", true) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableNamesIgnoreCase(); + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueEquals(variableName, variableValue); + + // greater than + queryValue = variableName + "_gt_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueGreaterThan(variableName, variableValue); + + // greater than equals + queryValue = variableName + "_gteq_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueGreaterThanOrEquals(variableName, variableValue); + + // lower than + queryValue = variableName + "_lt_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueLessThan(variableName, variableValue); + + // lower than equals + queryValue = variableName + "_lteq_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueLessThanOrEquals(variableName, variableValue); + + // like + queryValue = variableName + "_like_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueLike(variableName, variableValue); + reset(mockQuery); + + // like case-insensitive + queryValue = variableName + "_like_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .queryParam("variableValuesIgnoreCase", true) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueLike(variableName, variableValue); + + // not equals + queryValue = variableName + "_neq_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).processVariableValueNotEquals(variableName, variableValue); + reset(mockQuery); + + // not equals case-insensitive + queryValue = variableName + "_neq_" + variableValue; + + given() + .queryParam("processVariables", queryValue) + .queryParam("variableValuesIgnoreCase", true) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueNotEquals(variableName, variableValue); + } + + @Test + public void testProcessVariableValueEqualsIgnoreCaseAsPost() { + Map variableJson = new HashMap<>(); + variableJson.put("name", SAMPLE_VAR_NAME); + variableJson.put("operator", "eq"); + variableJson.put("value", SAMPLE_VAR_VALUE.toLowerCase()); + + List> variables = new ArrayList<>(); + variables.add(variableJson); + + Map json = new HashMap<>(); + json.put("processVariables", variables); + json.put("variableValuesIgnoreCase", true); + + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(json) + .header("accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueEquals(SAMPLE_VAR_NAME, SAMPLE_VAR_VALUE.toLowerCase()); + } + + @Test + public void testProcessVariableNameEqualsIgnoreCaseAsPost() { + Map variableJson = new HashMap<>(); + variableJson.put("name", SAMPLE_VAR_NAME.toLowerCase()); + variableJson.put("operator", "eq"); + variableJson.put("value", SAMPLE_VAR_VALUE); + + List> variables = new ArrayList<>(); + variables.add(variableJson); + + Map json = new HashMap<>(); + json.put("processVariables", variables); + json.put("variableNamesIgnoreCase", true); + + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(json) + .header("accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableNamesIgnoreCase(); + verify(mockQuery).processVariableValueEquals(SAMPLE_VAR_NAME.toLowerCase(), SAMPLE_VAR_VALUE); + reset(mockQuery); + + json.put("variableValuesIgnoreCase", true); + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(json) + .header("accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableNamesIgnoreCase(); + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueEquals(SAMPLE_VAR_NAME.toLowerCase(), SAMPLE_VAR_VALUE); + + } + + @Test + public void testProcessVariableValueNotEqualsIgnoreCaseAsPost() { + Map variableJson = new HashMap<>(); + variableJson.put("name", SAMPLE_VAR_NAME); + variableJson.put("operator", "neq"); + variableJson.put("value", SAMPLE_VAR_VALUE.toLowerCase()); + + List> variables = new ArrayList<>(); + variables.add(variableJson); + + Map json = new HashMap<>(); + json.put("processVariables", variables); + json.put("variableValuesIgnoreCase", true); + + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(json) + .header("accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueNotEquals(SAMPLE_VAR_NAME, SAMPLE_VAR_VALUE.toLowerCase()); + } + + @Test + public void testProcessVariableValueLikeIgnoreCaseAsPost() { + Map variableJson = new HashMap<>(); + variableJson.put("name", SAMPLE_VAR_NAME); + variableJson.put("operator", "like"); + variableJson.put("value", SAMPLE_VAR_VALUE.toLowerCase()); + + List> variables = new ArrayList<>(); + variables.add(variableJson); + + Map json = new HashMap<>(); + json.put("processVariables", variables); + json.put("variableValuesIgnoreCase", true); + + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(json) + .header("accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueLike(SAMPLE_VAR_NAME, SAMPLE_VAR_VALUE.toLowerCase()); + } + + @Test + public void testProcessVariableValueNotLikeIgnoreCaseAsPost() { + Map variableJson = new HashMap<>(); + variableJson.put("name", SAMPLE_VAR_NAME); + variableJson.put("operator", "notLike"); + variableJson.put("value", SAMPLE_VAR_VALUE.toLowerCase()); + + List> variables = new ArrayList<>(); + variables.add(variableJson); + + Map json = new HashMap<>(); + json.put("processVariables", variables); + json.put("variableValuesIgnoreCase", true); + + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(json) + .header("accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXTERNAL_TASK_QUERY_URL); + + verify(mockQuery).matchVariableValuesIgnoreCase(); + verify(mockQuery).processVariableValueNotLike(SAMPLE_VAR_NAME, SAMPLE_VAR_VALUE.toLowerCase()); + } + private List createMockExternalTasksTwoIds() { return Arrays.asList( MockProvider.mockExternalTask().buildExternalTask(), From 2e40a98ff49b51777a1cd9d3b7b5729aaeda94ce Mon Sep 17 00:00:00 2001 From: Stijn Vlaes Date: Mon, 18 Aug 2025 13:46:00 +0200 Subject: [PATCH 3/3] feat(rest): variable and process definition queries for external tasks - fixes ExternalTaskRestServiceQueryTest.testCompleteGETQuery related to https://github.com/camunda/camunda-bpm-platform/issues/5334 --- .../bpm/engine/rest/ExternalTaskRestServiceQueryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java index f0fdaca6d3c..292b6dd3cbb 100644 --- a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ExternalTaskRestServiceQueryTest.java @@ -180,7 +180,7 @@ public void testCompleteGETQuery() { parameters.put("processDefinitionId", "someProcessDefinitionId"); parameters.put("processDefinitionVersionTag", "someProcessDefinitionVersionTag"); parameters.put("processDefinitionKey", "procDefKey"); - parameters.put("processDefinitionKeyIn", "procDefKey1,procDefKey2"); + parameters.put("processDefinitionKeyIn", "procDefKey2,procDefKey3"); parameters.put("processDefinitionName", "procDefName"); parameters.put("processDefinitionNameLike", "procDefName%"); parameters.put("active", "true");