Add event handler (ExecutionListener or TaskListener) at runtime

According to Camunda’s doc (https://docs.camunda.org/manual/latest/user-guide/process-applications/process-application-event-listeners/) a “global” event handler (ExecutionListener or TaskListener) can be added to the ProcessApplication.

Nonetheless, I have not been able to find a way to add a similar (“global”) event handler at runtime. This feature was present in Activiti using the method addEventListener of the engine’s RuntimeService (https://www.activiti.org/javadocs/org/activiti/engine/RuntimeService.html#addEventListener-org.activiti.engine.delegate.event.ActivitiEventListener-) but is no longer present in Camunda’s RuntimeService.

How could I add a “global” event handler at runtime?

Note: The ProcessApplication to which the event handlers will be added can not be modified since I want to add the handlers from a different library.

Thank you all,

So, you want to add global listeners by simply adding libraries to the classpath?

Assuming that your listeners can implement a custom marker interface like e.g. GlobalTaskListener and that Spring is available, you could enhance your ProcessApplication to have two autowired fields that collect all global task/execution listeners and return these lists in the respective methods.
Spring will then then collect and inject the listeners during startup.

@Autowired
List<GlobalTaskListeners> taskListeners;

public TaskListener getTaskListener() {
    return taskListeners;
}

Thanks for your answer.
But how do I “enhance” my process application? The way I would like to add the listeners is via an annotation for example, this means that I cannot modify the process application.
Is my reasoning correct?

You mentioned the ProcessApplication in your original post. That gave me the impression that you already created your own ProcessApplication subclass by extending one of the provided ones, just like it is shown in the docs you linked.
By enhancing I meant to add the mentioned fields and methods to your ProcessApplication class.

For sake of clarity, my original idea in more detail:

@ProcessApplication
public class MyProcessApplication extends ServletProcessApplication {
  @Autowired
  List<GlobalTaskListeners> taskListeners;

  public TaskListener getTaskListener() {
    return taskListeners;
  }
}

Please note that the above code is just a concept and is not guaranteed to work as-is.

Oh, I see. In fact I have no access whatsoever to the ProcessApplication.

More generally, would you happen to know any way in Camunda to handle any event (e.g. transitions, task achieved, etc.) and that can be added in runtime (or at least in any way to a third-party / deployed application)?

Hi @underscorenico,

There is no such feature. I also don’t think an API similar to Activiti’s API would be a good idea. In a shared engine scenario, this can easily result in memory leaks when you register a listener that is an instance of a class that belongs to a web application. When the web application is undeployed, the listener is still registered with the engine.

Please expand on your use case, i.e. why you can’t have this code as part of a process application.

Cheers,
Thorben

Does the camunda-bpm-reactor-spring-starter extension handle just this sort of thing> It allows you to tap into all sorts of life-cycle events using a set of selectors. For example I can listen to all user task creation events in my application like so:

@Component
@CamundaSelector(type = "userTask", event = TaskListener.EVENTNAME_CREATE)
public class UserTaskListener extends ReactorTaskListener {
...
}

You can find it here: https://github.com/camunda/camunda-bpm-reactor