TL;DR;

Camunda bietet die Möglichkeit Variablen in einer Prozessinstanz zu speichern. Diese können Beispielsweise in JavaDelegates oder über die REST API verwendet werden. Außerdem bietet das Cockpit eine Benutzeroberfläche um sich die Variablen anzuschauen oder diese zu bearbeiten. Um aus einem JaveDelegate eine Variable zu schreiben muss einfach nur die Methode setVariable(String variableName, Object value) aufgerufen werden. Der so gespeichert Wert kann in einem nachfolgenden Task mit der Methode getVariable(String variableName) wieder ausgelesen werden.

Beim letzten Mal haben wir uns angeschaut, wie man mit Hilfe von Servicetasks beliebigen Java Code in einen Prozess einbindet. Leider ergibt ein einzelner Servicetask meistens noch keinen ganzen Prozess, weshalb wir im Normalfall mehrere Tasks verwenden um die gewünschte Fachlichkeit zu modellieren. Dabei werden wir recht schnell an einen Punkt kommen, an dem wir Daten zwischen den verschiedenen Tasks austauschen müssen. Diese Anforderung löst Camunda mit den sogenannten „Prozessvariablen“, welche wir uns in diesem Artikel näher anschauen wollen.

Jede Prozessinstanz in Camunda hat mindestens einen „Variablen Scope“. In diesen können wir zur Laufzeit Daten, in Form von Variablen, ablegen oder diese abrufen. Den Variablen Scope kann man sich ein bisschen wie eine HashMap vorstellen. Jede Variable im Scope besteht aus einem eindeutigen Namen und einem dazugehörigen Wert.

 

Variablen in Service Tasks

Damit wir uns anschauen können wie wir die Variablen verwenden, habe ich das Beispiel aus dem letzten Artikel ein bisschen verändert. Der Prozess besteht jetzt nur noch aus zwei Servicetasks, welche beide als „Java Class“ implementiert sind. Der ersten Task soll eine Berechnung durchführen und das Ergebnis in einer Prozessvariable speichern. Diese Prozessvariable soll dann im zweiten Servicetask wieder ausgelesen werden.

Wenn wir uns jetzt die Implementierung der beiden Tasks anschauen, sehen wir, dass beide das Interface JavaDelegate implementieren und deshalb eine Methode mit der folgenden Signatur enthalten:

void execute(DelegateExecution delegateExecution) throws Exception

Diese Methode haben wir uns ja schon im letzten Artikel angeschaut. Allerdings haben wir dabei den Parameter vom Type DelegateExecution einfach ignoriert, weil wir ihn für das Beispiel nicht gebraucht haben. Das ändert sich wenn wir eine Variable in der aktuellen Prozessinstanz ablegen wollen. Dafür benötigen wir nämlich eine Referenz auf den Variablen Scope unseres Prozesses.

Ein Blick in die Dokumentation verrät uns, dass das Interface DelegateExecution das Interface BaseDelegateExecution erweitert, welches seinerseits wieder VariableScope erweitert.

Also ist unsere DelegateExecution gleichzeitig der Variable Scope den wir benötigen. Um damit jetzt eine Variable zu erstellen, müssen wir einfach nur die folgende Methode aufrufen:

setVariable(String variableName, Object value)

Als Parameter übergeben wir den Namen den unsere Variable haben soll und den Wert. Als Wert können die einfachen Datentypen von Java verwendet werden. Außerdem kann Camunda beliebige Objekte in serialisierter Form speichern. Standardmäßig werden die Objekte dafür mit Jackson in JSON konvertiert.

Unsere Delegate könnte Beispielsweise so aussehen:

@Component
public class DoCalculationDelegate implements JavaDelegate {
    public void execute(DelegateExecution delegateExecution) throws Exception {
        int result = 1 + 1;
        delegateExecution.setVariable("calculationResult", result);
    }
}

Schauen wir uns jetzt noch kurz an wie wir Variablen wieder aus dem Variable Scope auslesen können. Auch dafür bietet die DelegateExecution wieder die passende Methode:

getVariable(String variableName)

Damit können wir jetzt die Variable auslesen und im Terminal ausgeben.

@Component
public class UseCalculationDelegate implements JavaDelegate {
    public void execute(DelegateExecution delegateExecution) throws Exception {
        Integer result = (Integer)delegateExecution.getVariable("calculationResult");
        System.out.println("Result: " + result);
    }
}

Wenn wir die Anwendung jetzt ausführen und über die Tasklist eine neue Prozessinstanz starten, sollten wir unsere Result in der Ausgabe sehen:

Result: 2

Damit ist unsere Anforderung bereits umgesetzt. Natürlich bietet der Variablen Scope noch ein paar mehr Möglichkeiten. Man kann Beispielsweise Variablen löschen, oder sich alle bekannten Variablen auflisten lassen. Die JavaDocs bieten hier einen recht guten Überblick über die Möglichkeiten.

Das Beispielprojekt aus diesem Artikel findet ihr wie immer in meinem GIT Repository: https://github.com/pragtics/camunda-demos/tree/master/process-variables

 

Variablen im Cockpit

Auch im Camunda Cockpit kann man sich die Variablen einer laufenden Prozessinstanz anschauen und diese sogar bearbeiten. Um das zu zeigen habe ich mithilfe eines Timer Events noch 5 Minuten Wartezeit zwischen unsere beiden Tasks eingebaut. Ansonsten wäre die Instanz einfach viel zu schnell beendet worden.

blank

 

Variablen über REST

Natürlich können die Variablen auch über die Camunda REST API ausgelesen und modifiziert werden. Dafür benötigt ihr lediglich die ID eurer Prozessinstanz und ggf. den Namen der Variablen. Am besten schaut ihr euch dafür einfach mal die offizielle Dokumentation an.

 

Variablen Scope

Eingangs habe ich geschrieben das jede Prozessinstanz mindestens einen Variablen Scope hat. In unserem extrem vereinfachten Beispiel gibt es auch tatsächlich nur einen Scope. In komplexeren Prozessen ist es aber durchaus üblich das es mehrere parallele und verschachtelte Scopes gibt. Das Thema ist allerdings etwas komplexer, weshalb ich es in einem eigenen Artikel behandeln werden.