Hi folks,
I want to assign a newly created task to the User who completed the prior task (if no other assignee is specified in the model).
As this should happen for every task I tried to implement it with a global EventListener, listening to ‘create’ and ‘complete’ TaskEvents.
My approach is to save the assignee on completion into a local variable with the scope provided by EventListener#getExecutionId.
On creation I load the variable from the scope provided by EventListener#getExecutionId, including its parent scopes.
I am using Camunda with SpringBoot.
@EventListener(condition = "#taskEvent.eventName.equals('create')")
public void onCreate(TaskEvent taskEvent)
{
if (isEmpty(taskEvent.getAssignee()))
{
String lastAssignee = (String) camundaRuntimeService.getVariable(taskEvent.getExecutionId(), "lastAssignee");
if (isNotEmpty(lastAssignee))
camundaTaskService.setAssignee(taskEvent.getId(), lastAssignee);
}
}
@EventListener(condition = "#taskEvent.eventName.equals('complete')")
public void onComplete(TaskEvent taskEvent)
{
String assignee = taskEvent.getAssignee();
if (isNotEmpty(assignee))
camundaRuntimeService.setVariableLocal(taskEvent.getExecutionId(), "lastAssignee", assignee);
}
I tested the code with the following process:
The creation event of the “noPresetAssignee” Task doesn’t find the “lastAssignee” variable which was set in “initialTask”.
I have the following questions:
- Why is the “lastAssignee” variable not accessible from “noPresetAssignee”'s scope, which should be a child of “initialTask”'s scope if I am not mistaken?
- Might there be another way to accomplish my goal?
I would really appreciate your input!
Hello @jannisEis ,
there is a way to do this. As assignee, you can use this expression:
${currentUser()}
This will assign the task to the user who completed the last task before.
Hope this helps
Jonathan
Hello @jonathan.lukas ,
thank you for the fast reply!
Unfortunately your approach won’t work reliably if there is a timer event between Task A and Task B.
Do you have any insight to why the approach of saving the assignee to a local variable does not work? I feel like I might have some misconception of variable scopes.
Hello @jannisEis ,
a localVariable is saved in the local scope of a task, so after the task is finished, this local variable disappears.
Using a common variable to store the user enables you to assign him with an expression in the assignee field.
To (maybe) further improve the behaviour, it also possible to save the user id of the initiator as process instance variable. To do this, in the start event, you can fill the field “initiator” in the properties panel with the variable name you wish.
Hope this helps
Jonathan
Good morning @jonathan.lukas ,
if I saved the variable to the task scope I would understand that it isn’t available after the task’s completion. But if I am not entirely mistaken I don’t do that, as you can see in the code snippet I take the execution of the task and save the variable locally to that execution.
From your documentation Variable Scopes and Variable Visibility I gathered that by running through the parallel gateway there should be a separate execution for each branch with its own local variable scope. The overlying execution scope of the tasks is the place where I intend to store the variable.
Thank you for your time
Jannis
Hello @jannisEis ,
this might be misleading, but the execution refers to the task.
So, creating a variable inside a task in local scope will lead to a variable that is only available inside this task.
Hope this helps
Jonathan
Hey @jonathan.lukas ,
I don’t mean to be impertinent, but my tests suggest that your statement is not true.
Using the following code I’m setting local variables via the execution I get from the incoming task.
@EventListener(condition = "#task.eventName.equals('create')")
public void onCreate(DelegateTask task)
{
if (isEmpty(task.getAssignee()))
{
String lastAssignee = (String) task.getVariable(NEXT_ASSIGNEE);
if (isNotEmpty(lastAssignee))
task.setAssignee(lastAssignee);
}
}
@EventListener(condition = "#task.eventName.equals('complete')")
public void onComplete(DelegateTask task)
{
String assignee = task.getAssignee();
DelegateExecution execution = task.getExecution();
if (execution != null)
execution.setVariableLocal(NEXT_ASSIGNEE, isNotEmpty(assignee) ? assignee : null);
}
The assignment in this test process works exactly as expected.
That is not the case if I use
DelegateTask#setVariableLocal
instead.
The code does not work for the initially posted process though. Adding another parallel gateway into a branch of a parallel process breaks the code.
What I observed was that on the second parallelization only one new Execution is created, while the other task refers to the same Execution that existed before the gateway.
Interestingly the newly created Execution is now a sibling to the Execution existing prior to the gateway, both having the processInstance as parent.
In this light it does make perfect sense why one of the Executions cannot access the variables set prior to the gateway.
The thing that I don’t get is why the gateway doesn’t properly split the Execution.
Best regards
Jannis
Hello @jannisEis ,
this is a very interesting experiment and fact. The behaviour I described was the one that worked for me, so I just “ignored” the execution of the parallel gateway and focused either on my task or my process (or subprocess).
I am not sure whether this behaviour is intended. @Ingo_Richtsmeier are you aware of this behaviour of executions?
Sorry I could not help you any further.
Jonathan