Modellierung und Einbindung eines BPMN-Prozesses – Teil 2

Für Sie interessant:

 

Open Source Businesslösungen

In dem Seminar Open Source Businesslösungen lernen Sie kompetente Entscheidungen für den Einsatz von speziellen Open Source Lösungen zu treffen.

Dies ist Teil 2 einer Artikel-Serie zur Prozessautomatisierung mit BPMN und Activiti.
Im einleitenden ersten Teil geht es um die vorbereitenden Tätigkeiten, die notwendig sind, um die angebotenen Dienste zur Steuerung der Prozessautomatisierung der Laufzeitumgebung nutzen zu können.
Im dritten und letzten Teil geht es um den Aufruf der Activiti Engine und seiner Services.

Im einleitenden Artikel dieser Serie wurden die notwendigen Vorbereitungen getroffen, um die angebotenen Dienste zur Steuerung der Prozessautomatisierung der Laufzeitumgebung nutzen zu können. Das Java-Projekt steht also nun. Im nächsten Schritt liegt der Fokus auf dem zu implementierenden Prozessablauf.

Das Beispielszenario

Bild: Flickr.com / photosteve101

Bild: Flickr.com / photosteve101

Im folgenden Beispiel sucht eine Castingagentur für einen bedeutenden Großkunden ein neues, weibliches Model. Jede Bewerberin (bzw. ihre Daten) muss beim Auswahlprozess folgende Prozedur durchlaufen: Es wird davon ausgegangen, dass beim Start des Prozesses die wichtigsten Daten von dem potentiellen Model vorliegen. Dazu zählen unter anderem Name, E-Mail-Adresse, Größe und Gewicht. Ebenso liegt eine URL zu einem Bild der Person zu Beginn bereits vor. Wie diese Daten übermittelt werden, ob z. B. digital, sei an dieser Stelle erstmal nicht relevant.

Doch auch dieses Szenario ließe sich ebenfalls mit der BPMN beschreiben.

Da sich über den Tag verteilt zahlreiche Frauen bei der Castingagentur melden und die Mitarbeiter weitest möglich entlastet werden sollen, existiert der (Java-)Service CheckAbilityService, der schon mal vorweg die Spreu vom Weizen trennen soll. Konkret ermittelt er anhand des Body-Mass-Indexes (BMI) der Bewerberin ihre generelle Eignung als Model in Bezug auf Größe und Gewicht.

Ist die Person vom Service als geeignet gekennzeichnet, schaut sich ein Mitarbeiter das zu der Person gehörende Foto an. Möchte der Mitarbeiter im Anschluss die Person näher kennen lernen, wird eine Einladung zu einem persönlichen Gespräch verschickt. Sollte der Mitarbeiter jedoch anhand des zur Verfügung stehenden Bildes keine Notwendigkeit für ein persönliches Gespräch erkennen, wird eine Absage übermittelt.

Ebenfalls erhält die Bewerberin eine Absage, wenn der CheckAbilityService sie aufgrund ihres BMI als ungeeignet deklariert.

Implementierung der Services

Für die Umsetzung des beschriebenen Prozesses werden zwei Services benötigt:
Zum einen wird der CheckAbilityService benötigt, der anhand eines Gewichts und einer Größe ermittelt, ob die dazugehörige Person für das Modeln geeignet ist. Zur Bewertung wird hierzu der BMI berechnet. Alle Personen mit einem BMI größer 21 seien in diesem Beispiel nicht geeignet.
Konkret bekommt die Service-Methode hasPotential Gewicht und Größe übergeben und liefert die Modeleignung als Wahrheitswert zurück (true = geeignet; false = nicht geeignet). Folgende Klasse wird erstellt:

package de.lmis.hhu.activiti.services;

import java.util.logging.Level;
import java.util.logging.Logger;

public class CheckAbilityService {

    private static CheckAbility Service INSTANCE = new CheckAbilityService();

    private CheckAbilityService() {

    }

    public static CheckAbilityService getInstance() {
        return INSTANCE;
    }

    public boolean hasPotential(double weight, int height) {
        double bmi = weight/(((double)height/100)*((double)height/100));
        if(bmi<=21){
            Logger.getLogger(CheckAbilityService.class.getName()).log(Level.INFO, "The BMI is "+bmi+" and is perfect!");
            return true;
        } else{ 
            Logger.getLogger(CheckAbilityService.class.getName()).log(Level.INFO, "The BMI is "+bmi+" and is poor!");
            return false;
        }
    }
}

Für das Versenden von Nachrichten wird ein weiterer Service benötigt, den SendMessageService. In der realen Welt würde die Nachricht natürlich per E-Mail verschickt werden. In diesem Beispiel wird sie einfachheitshalber im Log ausgegeben. Dazu wird die sendMessage-Methode implementiert, die als Übergabeparameter eine E-Mail-Adresse, einen Betreff und eine Nachricht bekommt. Folgender Quellcode zeigt die entsprechende Implementierung:

package de.lmis.hhu.activiti.services;

import java.util.logging.Level;
import java.util.logging.Logger;

public class SendMessageService {

    private static final SendMessageService INSTANCE = new SendMessageService();

    private SendMessageService() {

    }

    pubic static SendMessageService getInstance() {
        return INSTANCE;
    }

    public void sendMessage(String mailAddress, String subject, String message) {
        String logMessage = "Send message to '" + mailAddress + "' with subject '" + subject + "' and message '" + message + "'";
    Logger.getLogger(SendMessageService.class.getName()).log(Level.INFO,logMessage);
    }
}

Adapter-Bau für die Services

Innerhalb des Prozess-Modells werden später verschiedene so genannte ServiceTasks definiert, also Aktivitäten, die einen (Java-)Service aufrufen sollen (z. B. den CheckAbilityService). Es wird jedoch nicht die Service-Methode direkt aufgerufen, sondern (Adapter-)Klassen, die das Interface JavaDelegate implementiert haben.

package de.lmis.hhu.activiti.adapter;

import java.util.Map;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;

import de.lmis.hhu.activiti.services.CheckAbilityService;

public class CheckAbilityAdapter implements JavaDelegate {

  public void execute(DelegateExecution de) throws Exception {
    Map<String, Object> variables = de.getVariables();

    String heightString = (String) variables.get("height");
    String weightString = (String) variables.get("weight");

    int height = Integer.valueOf(heightString);
    double weight = Double.valueOf(weightString);

    boolean hasPotential = CheckAbilityService.getInstance().hasPotential(weight,height);
    de.setVariable("hasPotential", hasPotential)
  }

}

Abbildung 3 zeigt den Quellcode der Adapter-Klasse zum CheckAbilityService. Sie implementiert das zur Activiti Engine gehörende Interface JavaDelegate mit der execute-Methode. Diese Methode wird später von der Activiti Engine automatisch aufgerufen.
Der execute-Methode wird ein DelegationExecution-Objekt übergeben. Mit diesem Objekt kann unter  anderem auf vorher definierte Prozessvariablen zugegriffen werden.
Für den Aufruf des CheckAbilityServices werden die Größe und das Gewicht benötigt, die sich über das übergebene Objekt holen lassen (Zeile 15 und 16). Zusätzlich wird das DelegationExecution-Objekt genutzt, um neue Variablen innerhalb des Prozesses zu deklarieren, wie z. B. das Ergebnis des CheckAbilityServices (Zeile: 23).

Modellierung des Prozesses

Die Activiti Engine arbeitet mit BPMN-Modellen. Folglich wird der oben beschriebene Prozess noch modelliert. Folgendes BPMN-Modell soll den sehr vereinfachten – und zugegebenermaßen sehr oberflächlichen –  Prozess der Bewerberauswahl beschreiben:

BPMN-Modell zum Prozess der Bewerberauswahl (ModelCastingProcess.bpmn)

Das Modell wird mit dem Activiti Designer, einer weiteren Komponente aus dem Activiti Umfeld, erstellt. Es ist empfehlenswert, hierfür den Activiti Designer zu nutzen, denn als Plugin für die Entwicklungsumgebung Eclipse erleichtert es das Handling mit den fertigen Modellen erheblich. Ein ständiger Wechsel zwischen Modellierungswerkzeug und Entwicklungsumgebung fällt somit weg.
Da es sich bei BPMN um eine standardisierte Modellierungssprache handelt, kann natürlich jedes andere BPMN 2.0-kompatible Modellierungswerkzeug genutzt werden.

Die Installation des Activiti Designers ist simpel, sofern schon einmal Erfahrung mit der Installation eines Plugins in Eclipse gesammelt wurde. Eine detaillierte Beschreibung zur Installation, sowie zur Verwendung des Activiti Designers findet sich hier.

Ein Vorteil bei der Nutzung des Activiti Designers ist der Zugriff innerhalb eines ServiceTasks auf vorhandene Java Klassen:
Bei Auswahl eines ServiceTasks wird automatisch die Eclipse-View „Properties“ geöffnet. Dort können zu dem ausgewählten Baustein erweiterte Einstellungen vorgenommen werden. In diesem Fall wird im Reiter „Main config“ die zum ServiceTask gehörende Adapter-Klasse ausgewählt, da sie bzw. ihre execute-Methode innerhalb dieser Aktivität aufgerufen werden soll:

Angabe des Adapters innerhalb der ServiceTask „check ability for modeling“

Auf ähnliche Weise, allerdings mit vorheriger Auswahl eines Sequenzflusses, lassen sich die Verzweigungsbedingungen definieren. In folgender Abbildung ist die Bedingung für den Sequenzfluss zur UserTask „check appearance“ zu sehen. Sie soll ausgeführt werden, falls das Ergebnis (hasPotential) des CheckAbilityServices positiv ist.

Definition einer Verzweigungsbedingung

Einbindung des Prozess-Modells

Der Activiti Designer speichert BPMN-Modelle in einem XML-Format mit der Dateiendung „.bpmn“ ab. Es handelt sich zwar um eine XML-Datei, aber die Activiti Engine versteht diese Dateiendung nicht. Aus diesem Grund wird die Dateiendung durch „.bpmn20.xml“ ersetzt. So wird aus dem Dateinamen ModelCastingProcess.bpmn –> ModelCastingProcess.bpmn20.xml

Die entstandene XML-Datei wird als Ressource in den entsprechenden Ordner abgelegt. Der Ressourcen-Ordner sieht nun wie folgt aus:

Projektstruktur - Ablage der Activiti-Konfiguration

Artikel-Serie „Prozessautomatisierung mit BPMN und Activiti“

Bei diesem Blog-Eintrag handelt es sich um den zweiten von insgesamt drei Beiträgen zum Thema „Prozessautomatisierung mit BPMN und Activiti“.

Den einleitenden Teil 1 des Artikels finden Sie hier .

Im dritten und letzten Teil geht es um den Aufruf der Activiti Engine und seiner Services.

Bildquelle: Flickr.com nach Lizenzbestimmungen Creative Commons „CC BY 2.0“ (www.planetofsuccess.com/blog)