Blog

Bonita und die Sichtbarkeit von Variablen im Prozess

Die BPM-Lösung Bonita Open Solution bietet die Möglichkeit, Prozesse zu modellieren und diese später mit Daten und Logik auszustatten. Diese Daten werden entweder eingegeben oder aus einem Backend gelesen und sollen gegebenenfalls für spätere Entscheidungen in Gateways verwendet werden. Dass die Menge an der im Prozess mitgeführten Daten Einfluss auf die Performanz des Systems hat, wurde aber schon in einem anderen Blog-Eintrag behandelt.

Bonita (in der Version 5.6.3) bietet leider nur eine begrenze Kontrolle über die Sichtbarkeit und Verfügbarkeit von Prozessdaten. Diese können entweder Pool-weit oder nur in einer Aktivität gültig sein. Bei Sichtbarkeit über den ganzen Pool stehen die Variablen im gesamten Bonita-Prozess zur Verfügung. Alle dort enthaltenen Aktivitäten, Gateways, Transitionen usw. können auf die Variablen zugreifen und sie verändern. Aktivitäts-Variablen hingegen sind nur sehr kurz sichtbar: Nur wenn die Aktivität gerade aktiv ist, sowie in allen verlassenden Transitionen kann auf die Daten zugegriffen und für Logik verwendet werden.

In BPMN werden Gateways für logische Entscheidungen verwendet. Würde man in Bonita aber ein Gateway hinter eine Aktivität setzen, so müssten die Daten im ganzen Pool sichtbar sein. Gerade für größere Prozesse ist dies nicht gewünscht, da die Vielzahl von Variablen im Prozess Fehler verursacht. Den Prozess in viele viele kleine Prozesse zu zerlegen, ist bei großen Projekten nicht immer einfach und verringert die Übersicht.

Ein einfacher Workaround besteht darin, die Gateways wegzulassen. Dies ist möglich, da Logik-Ausdrücke an die Transitionen und nicht an die Gateways geschrieben werden. Genau genommen, ist das Modell dann aber kein BPMN mehr, da Entscheidungen nicht in/an Aktivitäten überprüft werden dürfen – hierfür sind ja die Gateways vorgesehen. Auch wirft Bonita bei dem Weg öfters Warnings und gegebenenfalls wird irgendwann das Vorgehen blockiert.

Fragen wir doch den Prozess

Unbestreitbar ist ein großer Vorteil von solchen Business Process Engines, dass sie die Variablen von jedem Prozess-Schritt vorhalten und diese für die spätere Nachvollziehbarkeit des Durchlaufs abrufbar sind. In Bonita ist das nicht anders und diese Variablen stehen einem auch über die Bonita-API zur Verfügung. Warum also nicht über die API erfragen, welchen Wert die Aktivitäts-Variable hatte? Zu beachten ist natürlich, dass man bei wiederholten Aktivitäten die richtige Instanz nach den Variablen befragt. In der Regel benötigt man aber die letzte Instanz, und die lässt sich einfach ermitteln.

Der folgende Sourcecode lässt sich am besten als JAR-Datei in den Prozess integrieren. Für das Kompilieren wird noch die Abhängigkeit zur Bonita-API benötigt.

public final class BonitaProcessUtils {

public static final Comparator<ActivityInstance> COMPARE_ACTIVITIES_BY_END_DATE = new Comparator<ActivityInstance>() {

@Override
public int compare(ActivityInstance o1, ActivityInstance o2) {
if (o1 == null && o2 == null) {
return 0;
} else if (o1 == null) {
return 1;
} else if (o2 == null) {
return -1;
} else if (o1.getEndedDate() == null && o2.getEndedDate() == null) {
return 0;
} else if (o1.getEndedDate() == null) {
return 1;
} else if (o2.getEndedDate() == null) {
return -1;
}
return o1.getEndedDate().compareTo(o2.getEndedDate());
}};

private BonitaProcessUtils() {
// Util class
}

public static <T> T getVariableOfLastActivityInstance(ProcessInstance processInstance, String nameOfActivity, String nameOfVariable, Class<T> type) {
Set<ActivityInstance> activities = processInstance.getActivities(nameOfActivity);
if (activities == null || activities.isEmpty()) {
return null;
}

List<ActivityInstance> activityInstances = new ArrayList<ActivityInstance>(activities);
Collections.sort(activityInstances, COMPARE_ACTIVITIES_BY_END_DATE);

ActivityInstance activityInstance = activityInstances.get(activityInstances.size() - 1);
return type.cast(activityInstance.getLastKnownVariableValues().get(nameOfVariable));
}

public static <T> T getVariableOfLastActivityInstance(ProcessInstance processInstance, String nameOfActivity, String nameOfVariable, T defaultValue) {
T variableOfLastActivityInstance = (T)getVariableOfLastActivityInstance(processInstance, nameOfActivity, nameOfVariable, defaultValue.getClass());
return variableOfLastActivityInstance == null ? defaultValue : variableOfLastActivityInstance;
}
}

Danach stehen zwei Methoden zur Verfügung, die einem den Wert einer bestimmten Variable in einem bestimmten Prozess-Schritt verraten. Diese Variablen kann man dann in Transitionen an Gateways verwenden, obwohl die Variablen nur in der Aktivität sichtbar sind.

Die Verwendung im Prozess ist denkbar einfach. Hat man dem Prozess die JAR-Datei hinzufügt, kann man mit diesem Code den Wert der Variable „myVar“ der Aktivität „myActivity“ erfahren.

import de.holisticon.bonita.utils.BonitaProcessUtils;
return BonitaProcessUtils.getVariableOfLastActivityInstance(processInstance, "myActivity", "myVar", Boolean.class);

So kann man in Bonita korrekte BPM-Notation verwenden, ohne alle Variablen für Entscheidungen im Prozess vollständig mitzuführen. Als Nachteil erkauft man sich aber, dass die automatische Korrektur von Bonita beim Umbenennen der Aktivität oder der Variable nicht mehr angewendet werden kann. Es sollte daher genau abgewägt werden, wann dieser Workaround zur Anwendung kommt oder ob stattdessen lieber die Variable für alle Elemente sichtbar in den Prozess mitgeführt wird.

Über den Autor

Antwort hinterlassen