Notification on every process instance state change (to update the UI)

We’re building an app that will have a “work to be done” screen and a supervisor’s “dashboard” screen. Each screen’s content will depend on the current status of all of the process instances. For example, the “work to be done” screen might show the various instances sorted into groups based on the User Task that each instance is at in the process.

We’d like the screen to refresh automatically so that it reflects the current state, when process instances “move” from step to step.

The app is being developed in Node.JS, and we’re using the REST API to communicate with the Camunda server.

The least desirable way to do this would be to have a JavaScript polling loop on each page that needs this functionality – i.e., running in the browser. It would make an AJAX call to our Node.JS server, which would then get the current list of process instances (and their variables) from Camunda (via the REST API) and pass the data back in the AJAX call response. The JavaScript code on the client would then update the DOM. (And we could also use something like React or VUE to do the data binding to the DOM elements.)

A better alternative to polling/AJAX might be to use socket.io so that any page that needs this auto-update capability could listen on a particular event and update the DOM when needed. Our Node.JS server would emit the event (containing the updated process instance list) on the socket, but it would need a way to know when any process instance experiences a change in state.

If our server were Java-based, I believe we could use an Execution Listener, in order to be notified by Camunda when there is a change. However, since we’re using the REST API, that option is not available.

We could write a polling loop on our Node.JS server that issues the REST API calls to Camunda to get the process instance list, and perhaps add some intelligence on our side to determine whether any changes have been made before emitting the list to the socket. (After all, that’s the way the camunda-worker-node module associates local Node.JS workers with service tasks – it polls the Camunda server via the REST API for external tasks.)

But we were hoping that there might be a more efficient way to do it.

Any ideas would be very appreciated.

Why not putting an execution listener script in your model that triggers your little nodejs socket server to notify all the clients.

https://docs.camunda.org/manual/7.8/user-guide/process-engine/delegation-code/#execution-listener
https://docs.camunda.org/manual/7.8/user-guide/process-engine/scripting/#use-scripts-as-execution-listeners

Thanks; I didn’t realize that we could use a SCRIPT as an execution listener. Will dig into this approach and see if we can write a script to kick our NodeJS server via an API call to tell it that it should grab the new process instance list and broadcast it to the clients via the socket.

Not sure how capable these embedded scripts are in terms of sending data but its worth a try.

Apart from that I would also consider to still make the clients pull the data and use the socket only to broadcast a signal that replaces the polling.

@kilsen you can also leverage Java classes through the scripts. So you can use Javascript (Nashorn) to send a TCP message to your node JS server for example. But you can use a Java TCP lib and access it through JS.

Here is a example with Redis: Storing process variables: Json (Spin) vs. String / what are the impacts?

We were able to get the JavaScript-based listener to make an API call to our Node.JS server. Upon receiving that API, our server fetches the task list from Camunda and emits it via the socket to any client pages that are listening. The plumbing all seems to work, but there’s still an apparent timing issue. We tried using the script on our user task, on Execution#start and also on Task#create. In either scenario, when we fetch the task list – which we expect will be updated, and will reflect the process instance in the new user state – we don’t get updated information; the process instance is still in the previous state. It’s as if the user task has not actually been created yet, when those listeners are invoked.

You can implement the task listener such that it only sends a notification after the current transaction is committed. See these two threads for an explanation and example code:

1 Like

Thanks for the suggestion. But it’s unclear to us how we could leverage this approach given that we’re writing a JavaScript-based listener. Is there some way that we can cause Camunda to fire an additional event AFTER the task has been created? Thus, instead of listening for Task#create, we’d listen for Task#created – and at that point, we’d properly see the process instance in its new state?

With Javascript running in the JVM (Nashorn), you can use Java classes and objects as documented here: The Nashorn Java API.

Afaik, there is no other kind of listener/event than the approach I mentioned.

1 Like

Thanks for the follow-up.

We ended up putting a non-interrupting timer boundary event on each of our user tasks, setting the duration to 0. The event is linked to a script task that uses JavaScript and Nashorn to make an HTTP request to our server, telling it that it’s time to fetch the updated list of tasks with variables. Thus whenever a process instance enters any user task, our server is notified. This clutters up our process diagram with a lot of little timer boundary stubs, but it gets the job done.

@kilsen that solution also creates a lot of background jobs for the Camunda Job executor to process. Should look at job starvation if you get a lot of process instances.

Thanks for the tip. How many process instances would you consider “a lot”? For the particular business process that we’re automating, there are approximately 2400 instances per month.

dont have a specific number. But just watch for stacking of jobs. can easily see this occur in the UI of cockpit.