Events after user task completion

I use Camunda 7.13 wit Spring Boot 2.4.2.

I’m looking for a way to get notified AFTER a user task is completed. Sure I know about “complete” event but with a little debugging it seems that all listeners are executed synchroneously in the same thread as completing is.

My goal is the following: When a user task is completed, my Spring Boot backend notifies my frontend that the list of active user tasks has changed. The frontend then queries the backend which queries TaskService.

In the above scenario I encounter random timing problems because the task is still available when querying the TaskService when the frontend is notified.

I could put the frontend websocket notification and TaskService query in a callable and do busy querying in a separate thread until the task has vanished from the query result, but that’s really ugly imho.

Does anyone know about a sure method to get notified when a task is “really” completed?

Wanted to just point about that officially Camunda 7.13 doesn’t support that version of spring boot. check out this matrix for more information.

So that is true - but the task is only officially complete once it’s been committed to the database. if you wanted to achieve something commits to the DB right after a task is complete you can add an async afteron the user task. That might help

1 Like

Thanks for your answer. I’ve tried setting async after on the user task, but still the notify is executed synchroneously while CompleteTaskCmd is still executing. See stack below.

BroadcastUserTaskListChanged notifies the websocket (in a different thread) there’s still the “race condition” where the frontend queries the task list too early.

notify:41, BroadcastUserTaskListChanged (my.task.listener)
invoke:45, TaskListenerInvocation (org.camunda.bpm.engine.impl.task.delegate)
proceed:58, DelegateInvocation (org.camunda.bpm.engine.impl.delegate)
handleInvocationInContext:92, DefaultDelegateInterceptor (org.camunda.bpm.engine.impl.delegate)
handleInvocation:63, DefaultDelegateInterceptor (org.camunda.bpm.engine.impl.delegate)
notify:62, DelegateExpressionTaskListener (org.camunda.bpm.engine.impl.task.listener)
invoke:45, TaskListenerInvocation (org.camunda.bpm.engine.impl.task.delegate)
proceed:58, DelegateInvocation (org.camunda.bpm.engine.impl.delegate)
handleInvocationInContext:92, DefaultDelegateInterceptor (org.camunda.bpm.engine.impl.delegate)
handleInvocation:63, DefaultDelegateInterceptor (org.camunda.bpm.engine.impl.delegate)
invokeListener:1090, TaskEntity (org.camunda.bpm.engine.impl.persistence.entity)
invokeListener:1070, TaskEntity (org.camunda.bpm.engine.impl.persistence.entity)
fireEvent:1021, TaskEntity (org.camunda.bpm.engine.impl.persistence.entity)
transitionTo:1168, TaskEntity (org.camunda.bpm.engine.impl.persistence.entity)
complete:315, TaskEntity (org.camunda.bpm.engine.impl.persistence.entity)
completeTask:100, CompleteTaskCmd (org.camunda.bpm.engine.impl.cmd)
execute:81, CompleteTaskCmd (org.camunda.bpm.engine.impl.cmd)
execute:37, CompleteTaskCmd (org.camunda.bpm.engine.impl.cmd)

Hi @fjakop,

what about notifying on the start of the next user task?

You can check the user task as “Asynchronous before” to send the notification in the same transaction as the new task is created (and nothing else).

If you want it between tasks, you can use the take event on the sequence flow.

https://docs.camunda.org/manual/7.15/user-guide/process-engine/delegation-code/#execution-listener
https://docs.camunda.org/manual/7.15/user-guide/process-engine/transactions-in-processes/#understand-asynchronous-continuations

Hope this helps, Ingo

Hi @Ingo_Richtsmeier,
thanks for pointing that out. Surely I could use “take” on the outgoing flow, but in my opinion this has 2 drawbacks:

  1. The model is not easily understandable any more, because no one would expect a listener there
  2. I would have to add it on each and every subsequent sequence flow of a user task, not just using @EventListener(condition = "#taskDelegate.eventName=='complete'") which I do at the moment, letting each user task notify the application to reload the task list.

As for the rollback/completion issue @Niall mentioned: Right, without the async after I can never be sure that the process is not rolled back, but that is no issue here since the only purpose of notification is to reload the task list which would be fine also on rollback.

At the moment I’m stuck with

@Async
@EventListener(condition = "#taskDelegate.eventName=='complete'")
public void onTaskEventComplete(DelegateTask taskDelegate) throws InterruptedException {
    log.debug(String.format("Complete task %s", taskDelegate.getId()));
    Thread.sleep(500);
    messagingTemplate.convertAndSend("taklist-changed", "update");
}

which works fine but is a little bit smelly.