How to find a multiInstanceBody Task with a specific variable value

Hello,

I am using a user task with a multi instance body.

<bpmn:userTask id="multiTask" name="Multi Task">
	<bpmn:multiInstanceLoopCharacteristics camunda:collection="someIdList" camunda:elementVariable="someId" />
</bpmn:userTask>

The variable “someIdList” contains a list of Long values which are correctly put into the variable “someId” for every task.

Using the TaskService API I would like to find all task instances with a certain “someId”. I have tried these three different approaches, but alle of the result list are empty:

List<Task> list = taskService.createTaskQuery()
		.taskVariableValueEquals("someId", searchId)
		.list();
List<Task> list2 = taskService.createTaskQuery()
		.caseInstanceVariableValueEquals("someId", searchId)
		.list();
List<Task> list3 = taskService.createTaskQuery()
		.processVariableValueEquals("someId", searchId)
		.list();

I can see the variable in the Cockpit, so I should be able to find the task.
Am I missing something here, or might this be a bug?

Thanks for your help!

Cheers
Christoph

Hi Christoph,

The first query does not return results because it filters for variables that are local to the task instance. The someId variable is not local to the task instance but to the activity instance/execution that executes the user task.

The second query does not return results because it filters for variables present in the CMMN case instance that the task is part of. Since you are using a BPMN user task, this does not return a result.

The third query’s filter matches, if the process instance to which a task belongs has the specified variable assigned to any activity instance. In consequence, I would expect all tasks to be returned by this query. Please provide a failing test case (using the testing template) so that we can have a deeper look into this.

Now, to get the results you actually want, I see two possibilities (assuming the absence of bugs ;)):

  1. Map the variable into the task scope, for example by using a task listener that copies the variable when the task is created. Then you can use the taskVariableValueEquals filter. Of course this results in duplicated variables.
  2. Implement a native task query with a condition that suits your needs.

Cheers,
Thorben

Hi Thorben,

Thanks for your explanation. That really helped a lot!

I created the test case and pushed it to my github fork in the branch multiTaskVariableTest. The results are unexpected, since query #3 now finds all the tasks associated with the process and not just the one I was looking for.

I managed to find my error so I now get the same results in the deployed engine. I then implemented the work around you suggested and copy the variable into a local variable using a task listener. This works as you predicted using query #1.

Still, this might be interesting to investigate. Should I report this as a bug?

Again, thanks for your help!

Cheers,
Christoph

Hi @c.keimel,

Thank you for creating the test case. In fact, this is the expected behavior and that is what I tried to describe in my last post regarding query three. processVariableValueEquals matches a task, if there is a matching variable that has the same process instance id as the task. In consequence, the filter matches even if the variable is not accessible from the task that is returned by it.

I think the reason why this API behaves this way is that it is not a trivial task to decide in a SQL query whether a variable is visible from a task (or execution) due to the dynamic tree structure of variable scopes. For example, a task can be define in a sub process, that is defined in another subprocess, and that is defined in the root process. All of these scopes may hold variables that are visible to the task and a proper implementation would have to consider this.

Cheers,
Thorben

1 Like

Hi Thorben,

ok, that makes sense. Thanks for the insight!

Cheers,
Christoph

Hi @thorben,

I have a similar scenario. I am mapping the task variable into the task scope. I used this query to check for the variable value

SELECT v.TASK_ID_, b.bytes_ FROM act_ge_bytearray b, act_hi_varinst v where b.id_ = v.bytearray_id_ and v.proc_inst_id_ IN ( 123 ) AND v.name_ = ‘taskVariables’;

I was able to find the value for “someId” in the json.

I used below method to retrieve all the tasks with the a specific value for “someId” but it returned empty list.
List list1 = taskService.createTaskQuery().processInstanceId(“123”)
.taskVariableValueEquals(“someId”, searchId)
.list();

Am I missing something?