Business-Objekte, Verträge und Web-basierte Formulare in einem Beispielprozess

In diesem Beitrag wird die Nutzung der hier vorgestellten Neuerungen von Bonita 7 an einem Beispielprozess erläutert. Hierfür wird der im BPMS-Buch als einführendes Beispiel verwendete Angebotsprozess herangezogen. Die ursprüngliche mit Bonita 6 erstellte Version, die auch mit Bonita 7 unverändert läuft, findet sich hier zum Download. Das Prozessmodell selbst bleibt unverändert, ebenso die Definition der Akteure und ihre Zuordnung zum Organisationsmodell. Sie werden daher nicht noch einmal beschrieben.

Download des Angebotsprozesses (mit Bonita 7-Features)

Business-Objekte

Bisher wurden in dem Prozess gewöhnliche Prozessvariablen verwendet, zumeist einfache Strings. Man hätte auch eine selbst erstellte Java-Klasse als Datentyp verwenden und damit ein komplettes Angebot als Objekt verarbeiten können. In beiden Fällen sind die Inhalte der Prozessvariablen immer nur in der jeweiligen Prozessinstanz verfügbar. Um die Daten dauerhaft zu speichern und sie übergreifend nutzen zu können, muss man sie explizit mit Hilfe eines Datenbank-Konnektors in eine separate Datenbank schreiben.

In der neuen Version des Prozesses wird ein Business-Objekt verwendet. Hierfür wird zunächst ein Business-Datenmodell benötigt. Hierzu wird im Bonita Studio ein Business-Objekt-Typ „Angebot“ mit den gewünschten Attributen angelegt (siehe Abbildung 1). Neben gewöhnlichen Datentypen wie Strings oder Ganzzahlen können auch andere Business-Objekt-Typen als Datentyp verwendet werden. Im Beispiel enthält das Angebot ein Attribut „kunde“, wobei der Typ „Kunde“ selbst wiederum ein Business-Objekt-Typ ist, der ebenfalls links in der Liste auftaucht.

Bonita erzeugt aus diesen Angaben eine Angebots- und eine Kundentabelle in einer Datenbank sowie Java-Klassen für den einfachen Zugriff auf die Business-Objekte. Die Business-Objekte stehen auch für andere Prozesse zur Verfügung. So könnten z. B. die Kundendaten in weiteren Prozessen genutzt werden. Weiterhin generiert Bonita Standard-Abfragen für Business-Objekte (die man in dem abgebildeten Dialog unter dem Register „Queries“ findet). So stehen Abfragen wie „findByAnfragetext“ oder „findByPreis“ zur Verfügung, mit denen alle Angebote mit einem bestimmten Anfragetext oder einem bestimmten Preis gefunden werden können. Zudem kann man eigene Abfragen in JPQL (Java Persistence Query Language, ähnlich SQL) schreiben. Im Beispiel wurde eine Abfrage zum Finden von noch nicht fertiggestellten Angeboten geschrieben und eine zweite, mit der abgeschlossene Angebote gefunden werden können. Diese werden später in einer Application-Website zum Erstellen einer Angebotsübersicht verwendet.

Business Data Model_klein
Abbildung 1: Business-Daten-Modell (Zum Vergrößern anklicken)

Um Angebotsobjekte in dem Prozess nutzen zu können, wird im Pool eine Business-Variable vom Typ Angebot angelegt. Dies funktioniert ähnlich wie das Anlegen einer gewöhnlichen Prozessvariablen. Wie man in Abbildung 2 sieht, wird im Prozess nur noch die Business-Variable „angebot“ verwendet. Die in der alten Version genutzten Prozessvariablen wurden alle gelöscht. Der Eintrag für den Default-Wert in Abbildung 2 wird später hinzugefügt.

Business Variable_klein
Abbildung 2: Business-Variable „angebot“ (Zum Vergrößern anklicken)

Contract

Nun soll ein Formular zum Starten des Prozesses angelegt werden. Hierzu selektiert man den Pool. Bevor man eine „Instantiation Form“ anlegt, sollte man jedoch den Contract erstellen, in dem festgelegt wird, welche Daten von dem Formular zum Prozess zurückgegeben werden sollen. Über „Add from data…“ kann man den Contract aus der Business-Variable „angebot“ generieren lassen. Man muss lediglich auswählen, welche Attribute verwendet werden sollen. Zu Beginn des Prozesses werden lediglich der Text der Anfrage und die Kundendaten eingegeben, weshalb die anderen Attribute der Anfrage deselektiert werden. Der resultierende Contract ist in Abbildung 4 dargestellt. Die Einträge unter „Description“ werden später automatisch als Hinweistexte in das Formular übertragen.

Contract zur Instanziierung_klein
Abbildung 3: Der Contract für das Instanziierungsformular (Zum Vergrößern anklicken)

Zugleich mit dem Contract kann man sich ein Skript für die Initialisierung der Business-Variable „angebot“ generieren lassen. Dieses Skript legt nach dem Start des Prozesses ein neues Angebot-Objekt an und weist den Attributen die im Contract definierte, vom Instanziierungsformular zurückgebenen Werte an. Das Initialisierungsskript findet sich in dem in Abbildung 2 dargestellten Dialog zum Bearbeiten der Business-Variable „angebot“ unter „Default value“. Es kann anschließend noch manuell angepasst werden. Das generierte Skript in Abbildung 4 nutzt Groovy-Syntax, es ist jedoch auch gewöhnliche Java-Syntax möglich.

Initialisierungsskript_klein
Abbildung 4: Das Initialisierungsskript für die Business-Variable „angebot“ (Zum Vergrößern anklicken)

Instanziierungs-Formular

Nun kann man sich unter „Instantiation Form“ das auf dem Contract basierende Instanziierungsformular erzeugen lassen und im UI Designer bearbeiten Der UI Designer öffnet sich in einem Web-Browser, ist also nicht in das Bonita Studio integriert. In dem generierten Formular wurde für jedes Datenfeld aus dem Contract ein Eingabeelement angelegt (Abbildung 5). Zudem enthält das Formular zwei Variablen (im unteren Bereich von Abbildung 5): formInput und formOutput.

Generiertes Initialisierungssformular_klein
Abbildung 5: Das generierte Instanziierungsformular im UI Designer (Zum Vergrößern anklicken)

Die Variable formInput enthält eine Datenstruktur, die die in das Formular eingegebenen Daten aufnehmen kann. Abbildung 6 zeigt diese Struktur, die im JSON-Format vorliegt. Sie entspricht der Struktur des Contracts und enthält zunächst leere Strings für die einzugebenden Daten, da hier keine Defaultwerte angezeigt werden sollen. Die Eingabefelder des Formulars sind mit den Feldern der Variable „formInput“ verknüpft. So ist für das Eingabefeld „emailadresse“ bei den Parametern auf der rechten Seite unter „Value“ „formInput.angebotInput.kunde.emailadresse“ eingetragen. Dadurch wird eine dynamische Verknüpfung hergestellt. Gibt man später eine E-Mail-Adresse in das Formular ein, so erhält der zu „emailadresse“ gehörende String in der JSON-Struktur von formInput automatisch denselben Wert zugewiesen. formInput enthält somit die gesamten Eingabedaten des Formulars.

formInput JSON
Abbildung 6: Die JSON-Struktur der Variable „formInput“

Der Inhalt der zweiten Variable, formOutput wird beim Abschicken des Formulars an die Process Engine zurückgegeben. In diesem Beispiel wird nur die Struktur von formInput kopiert, da die Eingabewerte unverändert zurückgegeben werden sollen. Schließlich enthält das Formular einen Submit-Button. In dessen Parametern ist die beim Klicken durchzuführende Aktion („Start process“), die zu sendenden Daten (die Variable formOutput) und die URL der als nächstes anzuzeigenden Seite eingetragen. Über die Standard-URL „/bonita“ wird das Prozessportal mit der Taskliste erreicht.

Das von Bonita generierte Formular könnte so direkt eingesetzt werden. Zuvor ist es aber sinnvoll, noch einige Anpassungen des Layouts und der angezeigten Beschriftungen durchzuführen (Abbildung 7). Unter anderem wurden „Name“ und „Gewünschte Leistung“ als Pflichtfelder markiert.

Ueberarbeitetes Instanziierungsformular_klein
Abbildung 7: Das überarbeitete Instanziierungsformular im UI Designer (Zum Vergrößern anklicken)

Über „Preview“ kann man sich jederzeit eine Vorschau des fertigen Formulars anzeigen lassen. Diese wird in Abbildung 8 gezeigt. Hier ist auch zu sehen, dass die beim Contract eingegebenen Beschreibungen (Abbildung 4) als Hinweis in die Eingabefelder eingeblendet werden, wenn noch keine Eingabe erfolgt ist. Diese Platzhalter-Texte können aber auch im UI Designer in den Parametern des jeweiligen Eingabefeldes eingegeben oder geändert werden.

Vorschau Instanziierungsformular_klein
Abbildung 8: Vorschau des Instanziierungsformulars (Zum Vergrößern anklicken)

Task-Contracts

Die Contracts und Formulare für die einzelnen Tasks werden ganz ähnlich erstellt wie die für die Prozessinstanziierung. Beispielhaft wird der Task „Angebot kalkulieren“ betrachtet. In diesem Task soll ein Preis eingetragen werden. Es ist aber auch möglich, dass der Verkäufer zum Schluss kommt, dass das Angebot überarbeit werden muss, oder dass die Anfrage komplett abschlägig beschieden werden muss. Wird das Angebot zur Überarbeitung zurückgegeben, so soll ein Kommentar eingetragen werden, mit dem der technische Vertriebsmitarbeiter darüber informiert wird, was geändert werden muss. Im Contract für „Angebot kalkulieren“ wird daher festgelegt, dass die drei Attribute „preis“, „kommentar“ und „entscheidung“ zurückgegeben werden (Abbildung 9).

Contract Angebot kalkulieren_klein
Abbildung 9: Contract des Tasks „Angebot kalkulieren“ (Zum Vergrößern anklicken)

Den Contract kann man wieder aus der Business-Variablen „angebot“ erzeugen lassen, wobei man die nicht benötigten Attribute deselektiert. Im Falle des Instanziierungs-Contracts wurde in diesem Schritt ein Initialisierungsskript für die Business-Variable „angebot“ generiert. Bei dem Task soll jedoch kein neues Angebots-Objekt angelegt werden. Stattdessen sollen die vom Task zurückgegebenen Werte in die betreffenden Attribute des existierenden Objekts geschrieben werden. Dies geschieht mit Hilfe von „Operations“, die die setter-Methoden der zum Business-Daten-Modell erzeugten Java-Klasse verwenden (Abbildung 10).

Operations Angebot kalkulieren_klein
Abbildung 10: Operations zum Aktualisieren der Daten im Task „Angebot kalkulieren“ (Zum Vergrößern anklicken)

Formulare für die Tasks

Auch für jeden Tasks lässt sich aus seinem Contract ein Formular generieren, das im UI-Designer bearbeitet werden kann. Das generierte Formular für den Task „Antrag kalkulieren“ in Abbildung 11 ähnelt vom Prinzp her dem generierten Instanziierungsformular des Prozesses (Abbildung 5). Für jedes Attribut des Contracts wurde ein Eingabefeld generiert, zudem die Variablen „formInput“ zum Aufnehmen der Benutzereingaben und „formOutput“ und zur Rückgabe der Werte an den Prozess. Hinzu kommt eine Variable „taskID“ mit dem eindeutigen Identifier des Tasks, von dem aus das Formular aufgerufen wird, und eine Variable „context“.

Generierter Dialog Angebot kalkulieren_klein
Abbildung 11: Generierter Dialog für den Task „Angebot kalkulieren“ (Zum Vergrößern anklicken)

Über die in der Variablen „context“ enthaltenen Adresse kann man auf sämtliche in dem Task verfügbaren Daten zugreifen, im vorliegenden Beispiel auf die Inhalte der Business-Variablen „angebot“. Bislang kann man in das Formular zwar Eingaben tätigen, doch werden noch keine der vorher im Prozess eingegebenen Daten angezeigt. Letzteres kann mit Hilfe des „context“ erreicht werden.

Hierzu legt man im UI Designer eine Variable „angebot“ an. Sie ist vom Typ „External API“, d. h. sie erhält ihre Daten mittels des REST API aus der Process Engine. Ihr Inhalt „../{{context.angebot_ref.link}}“ adressiert die Business-Variable „angebot“ in der Process Engine. Die doppelten geschweiften Klammern enthalten einen Variablenausdruck, d. h. hier wird automatisch die in „context“ enthaltene Adresse eingesetzt. Über die im Formular angelegte Variable „angebot“ kann man nun die einzelnen Attributwerte ansprechen (z. B. „angebot.anfragetext“) und in einem Dialogfeld anzeigen. Abbildung 12 zeigt das überarbeitete Formular mit der neu angelegten Variablen „angebot“ und einigen als Read-only markierten Felder zur Anzeige von Kundenname, Anfragetext und Angebotstext.

Dialog Angebot kalkulieren_klein
Abbildung 12: Überarbeiteter Dialog für den Task „Angebot kalkulieren“ (Zum Vergrößern anklicken)

Im Vergleich zum generierten Formular fällt in Abbildung 12 auf, dass die vom Benutzer auszufüllenden Eingabefelder nicht mehr mit den betreffenden Attributen der Variablen „formInput“ verknüpft sind, sondern mit denen der Variable „angebot“. Wenn der Task „Angebot kalkulieren“ nach einer Überarbeitung erneut aufgerufen wird, dann sollen bereits vorhandene Inhalte von „preis“ und „kommentar“ angezeigt werden. Und diese finden sich in der Variablen „angebot“, die ja den Inhalt der gleichnamigen Business-Variable im Prozess enthält.

In dem überarbeiteten Formular in Abbildung 12 wurde das Eingabefeld für „entscheidung“ gelöscht. Die Entscheidung über das Angebot soll durch Auswahl einer der Schaltflächen „Annehmen“, „Ablehnen“ oder „Zur Überarbeitung zurück“ getroffen werden. Jede dieser drei Schaltflächen hat die Action „Submit Task“ und die Target URL „/bonita“ zugeordnet. Jede Schaltfläche beendet also den Task, und man gelangt anschließend wieder zum Bonita-Portal. Der einzige Unterschied besteht in den an das BPMS zurückgelieferten Daten („Data sent on click“). Für die Rückgabe jeder Schaltfläche wurde eine eigene Variable angelegt. So sendet die Schaltfläche „Abgelehnt“ den Inhalt der Variablen „formOutputAbgelehnt“ (vgl. Abbildung 13).

Ausschnitt aus Parametern fuer Schaltflaeche Abgelehnt
Abbildung 13: Ausschnitt aus den Parametern der Schaltfläche „Abgelehnt“

Bei „formOutputAbgelehnt“ handelt es sich um eine Variable vom Typ „Javascript expression“ (Abbildung 14). Diese Javascript-Expression gibt ein JSON-Objekt zurück, dessen Form dem Contract entspricht. Die Felder „preis“ und „kommentar“ erhalten über die gleichnamigen Attribute der Variable „angebot“ die Inhalte der betreffenden Eingabefelder. Dem Feld „entscheidung“ wird fest der Wert „abgelehnt“ zugeordnet.

Variable-FormOutputAbgelehnt
Abbildung 14: Die Variable „formOutputAbgelehnt“

Die Javascript-Expressions in den Variablen „formOutputAngenommen“ und „formOutputZuUeberarbeiten“ für die anderen beiden Schaltflächen sind genauso aufgebaut, setzen den Wert von „entscheidung“ jedoch auf „angenommen“ bzw. „zuUeberarbeiten“.

Damit das Angebot angenommen werden darf, muss in das Formular ein Preis eingetragen werden. Ebenso muss ein Kommentar eingetragen werden, wenn man das Angebot zur Überarbeitung zurücksendet. Die Überprüfung dieser beiden Regeln war in Bonita 6 nicht so einfach zu bewerkstelligen. Man kann die beiden Felder nicht zu Muss-Feldern erklären, da sie ja nicht in jedem Fall ausgefüllt werden müssen, sondern nur jeweils bei einer bestimmten Entscheidung. Im UI-Designer kann man dies recht einfach lösen, indem man die betreffenden Schaltflächen inaktiv setzt, solange im betreffenden Eingabefeld noch nichts eingetragen wurde.

Hierfür verfügen die Schaltflächen über einen Parameter „Disabled“. Für die Schaltfläche „Zur Überarbeitung zurück“ wurde hierfür der Ausdruck angebot.kommentar == null || angebot.kommentar == "" eingetragen. Solange es also noch keinen Kommentar gibt oder es sich um einen leeren String handelt, bleibt die Schaltfläche deaktiviert. Gibt man etwas ein, so wird die Schaltfläche sofort aktiv und kann zum Absenden des Formulars genutzt werden. Für die Schaltfläche „Annehmen“ wird auf die gleiche Weise überprüft, ob etwas im Feld „Preis“ eingetragen ist.

Mit den vorangehenden Erläuterungen lässt sich auch der Aufbau der Formulare für die anderen beiden User-Tasks in dem Prozess nachvollziehen. Nach dem Absenden eines Formulars wird die Business-Variable „angebot“ über die Operations des betreffenden Formulars mit den zurückgegebenen Werten aktualisiert. Die Aktualisierung betrifft auch die zugehörigen Datenbankeinträge.

Zugriff auf Business-Variablen in Bedingungen und Konnektoren

Da in dem Prozess keine gewöhnlichen Prozessvariablen mehr verwendet werden, muss in den Bedingungen am verzweigenden Gateway ebenso wie in den verwendeten E-Mail-Konnektoren auf die Inhalte der Business-Variablen „angebot“ zugegriffen werden. Dies erfolgt mit Hilfe der generierten getter- und setter-Methoden. So lautet etwa die Bedingung an dem mit „Angebot okay“ bezeichneten Gateway angebot.getEntscheidung()=="angenommen".

Schließlich werden noch einige Daten für die am Ende zu versendende E-Mail benötigt. So erhalten die verwendeten E-Mail-Konnectoren die Empfängeradresse mittels eines Skripts mit dem Inhalt angebot.getKunde().getEmailadresse(). Um Daten aus dem Angebot in den Text der E-Mail einfügen zu können, werden im Task „Angebot versenden“ zwei lokale Variablen „angebotstext“ und „preis“ definiert. Sie erhalten die entsprechenden Inhalten aus der Business-Variablen „angebot“ als Default-Werte. Im Textkörper der E-Mail können dann die Einträge „${angebotstext}“ und „${preis}“ verwendet werden. Sie werden bei der Prozessausführung durch die Inhalte der beiden Variablen ersetzt.

Damit ist der Prozess fertig konfiguriert und kann nun ausgeführt werden. Die sonstigen Inhalte, wie das Prozessmodell (mit Ausnahme des nicht mehr benötigten Rücksprungs nach „Angebot kalkulieren“) und die Zuordnung von Akteuren, sind unverändert gegenüber der ursprünglichen, mit Bonita 6 erstellten Version. Die Ausführung des Prozesses ist ebenso unverändert.

Die wesentlichen Vorteile des Business-Daten-Modells werden bei isolierter Betrachtung dieses einen Prozesses noch nicht deutlich. Wenn man jedoch auch in anderen Prozessen oder aus anderen Anwendungen heraus auf die in dem Prozess erfassten Daten zugreift, macht es sich bezahlt, dass die Daten automatisch in einer Datenbank gespeichert werden. Bei einer Weiterentwicklung dieses einfachen Beispielprozesses würde man zudem die Kundendaten nicht jedesmal aufs Neue erfassen, sondern bei einem wiederkehrenden Kunden eine Verknüpfung mit seinem existierenden Datensatz herstellen. Hierzu könnte man in das Formular zur Antragserfassung relativ einfach eine Suche und Auswahl von Kunden integrieren. Ohne die Verwendung des Business-Daten-Modells wäre es sehr umständlich, solche Funktionen zu implementieren.

Anwendung

Mit Hilfe des UI Designers kann man nicht nur Formulare zur Bearbeitung davon Benutzer-Tasks erstellen, sondern auch Seiten für „gewöhnliche“ Webanwendungen, die auf Ressourcen und Daten des BPMS zugreifen und mit Prozessen interagieren können. So kann man etwa einem Kunden in einem Webshop ein Formular zum Aufgeben einer Bestellung zur Verfügung stellen sowie eine Seite, auf der er den Status seiner Bestellungen einsehen kann. Dabei bekommt der Kunde gar nicht mit, dass im Hintergrund ein Prozess in einem BPMS ausgeführt wird. Die an dem Prozess beteiligten Mitarbeiter des Versandhändlers hingegen arbeiten mit der Taskliste des Prozessportals.

Als Beispiel wird eine kleine, nur aus einer Seite bestehende Anwendung vorgestellt, auf der eine Übersicht über die erstellten sowie die noch in Arbeit befindlichen Angebote angezeigt wird. Außerdem soll es möglich sein, von der Seite aus direkt einen neuen Angebotsprozess zu starten.

Abbildung 15 zeigt den Entwurf dieser Seite im UI Designer. Die beiden Variablen „abgeschlosseneAngebote“ und „angeboteInArbeit“ sind vom Typ „External API“. Über die hinterlegten URLs, z. B. „../API/bdm/businessData/com.company.model.Angebot?q=findAbgeschlosseneAngebote&p=0&c=10„, werden die für das Business-Daten-Modell definierten Abfragen adressiert. Die Variablen enthalten dann jeweils das Ergebnis der Abfrage im JSON-Format.

Die Listen im Formular sind mit Hilfe von Tabellen-Widgets realisiert worden. In der Abbildung sieht man rechts die Parameter des oberen Tabellen-Widgets. Dabei handelt es sich zum einen um eine Liste mit den Spalten-Überschriften, zum anderen um die Referenz auf die Variable „angeboteInArbeit“, die die Daten enthält. Unter „Column keys“ sind die Bezeichnungen der im Business-Daten-Modell festgelegten Attribute aufgeführt, die angezeigt werden sollen. Diese Attributnamen sind in der von der Abfrage gelieferten JSON-Struktur ebenfalls enthalten sind und können daher zum Zugriff auf die einzelnen Felder genutzt werden. Die untere Tabelle wird auf die gleiche Weise konfiguriert.

Entwurf Angebotsapplikation_klein
Abbildung 15: Entwurf der Angebotsübersicht im UI Designer (Zum Vergrößern anklicken)

Über die URL der Variablen „session“ enthält man eine Referenz auf die aktuelle Session. Über diese kann man herausfinden, welcher Benutzer gerade eingeloggt ist. Dies wird im Textfeld rechts oben genutzt, wo der Benutzername mittels {{session.user_name}} angezeigt wird.

Die Variable „processStartURL“ enthält die URL, über die der oben beschriebene Angebotsprozess gestartet werden kann. Sie ist unter anderem aus dem Namen und der Versionsnummer des Prozesses zusammengesetzt. Bei dem Button „Neues Angebot“ handelt es sich um ein Link-Widget, bei dem als Target Url die Variable „processStartURL“ eingetragen ist.

Um die Seite in der Anwendung nutzen zu können, muss man sie zunächst exportieren. Im Bonita-Portal muss man zur Administrator-Rolle wechseln. Dann kann man „Resources“ die vom UI Designer exportierte zip-Datei importieren. Anschließend legt man unter „Applications“ eine neue Application an. Hierbei muss man für den Aufruf der Anwendung eine URL festlegen, z. B. „angebote“. Dann kann man die Anwendung zur Bearbeitung öffnen. Unter „Pages“ klickt man auf „Add“ und wählt die gerade importierte Seite aus. Auch für die Seite muss eine URL festgelegt werden, z. B. „uebersicht“. Schließlich macht man die Seite zur Homepage und löscht die vorgegebene Standard-Homepage.

Angebotsapplikation_klein
Abbildung 16: Angebotsübersicht in der Anwendung (Zum Vergrößern anklicken)

Nun kann man die Anwendung direkt über ihre URL starten (z. B. „http://localhost:8080/bonita/apps/angebote“), und es wird die in Abbildung 16 dargestellte Übersicht angezeigt. Klickt man auf „Neues Angebot“, so wird der Dialog „Anfrage erfassen“ geladen, über den der Angebotsprozess gestartet wird.