Einführung in Flowable

1. Übersicht

Flowable ist eine in Java geschriebene Geschäftsprozess-Engine. In diesem Lernprogramm werden die Details der Geschäftsprozesse erläutert und erläutert, wie wir die Flowable Java-API zum Erstellen und Bereitstellen eines Beispielgeschäftsprozesses nutzen können.

2. Geschäftsprozesse verstehen

Einfach ausgedrückt ist ein Geschäftsprozess eine Reihe von Aufgaben, die, sobald sie in einer definierten Reihenfolge ausgeführt wurden, ein definiertes Ziel erreichen . Jede Aufgabe in einem Geschäftsprozess hat klar definierte Ein- und Ausgänge. Diese Aufgaben erfordern möglicherweise menschliches Eingreifen oder können vollständig automatisiert sein.

OMG (Object Management Group) hat einen Standard namens Business Process Model and Notation (BPMN) definiert, mit dem Unternehmen ihre Prozesse definieren und kommunizieren können . BPMN wird in der Branche weitgehend unterstützt und akzeptiert. Die Flowable-API unterstützt das Erstellen und Bereitstellen von BPMN 2.0-Prozessdefinitionen vollständig.

3. Prozessdefinitionen erstellen

Nehmen wir an, wir haben vor der Veröffentlichung einen einfachen Prozess für die Artikelüberprüfung.

Der Kern dieses Prozesses besteht darin, dass Autoren einen Artikel einreichen und die Redakteure ihn entweder akzeptieren oder ablehnen. Bei Annahme wird der Artikel sofort veröffentlicht; Bei Ablehnung wird der Autor jedoch per E-Mail benachrichtigt:

Wir erstellen Prozessdefinitionen als XML-Dateien unter Verwendung des BPMN 2.0-XML-Standards.

Definieren wir unseren einfachen Prozess gemäß dem BPMN 2.0-Standard:

Nun gibt es hier eine ganze Reihe von Elementen, die Standard-XML-Inhalte sind, während andere für BPMN 2.0 spezifisch sind:

  • Der gesamte Prozess ist in ein Tag namens "Prozess" eingeschlossen, das wiederum Teil eines Tags namens "Definitionen" ist.
  • Ein Prozess besteht aus Ereignissen, Flows, Aufgaben und Gateways
  • Ein Ereignis ist entweder ein Startereignis oder ein Endereignis
  • Ein Flow (in diesem Beispiel ein Sequenzfluss) verbindet andere Elemente wie Ereignisse und Aufgaben
  • Aufgaben sind dort, wo die eigentliche Arbeit erledigt wird; Dies können unter anderem „Benutzeraufgaben“ oder „Serviceaufgaben“ sein
  • Für eine Benutzeraufgabe muss ein menschlicher Benutzer mit der Flowable-API interagieren und Maßnahmen ergreifen
  • Eine Serviceaufgabe stellt eine automatische Aufgabe dar, bei der es sich um einen Aufruf einer Java-Klasse oder sogar um einen HTTP-Aufruf handeln kann
  • Ein Gateway wird basierend auf dem Attribut "Genehmigt" ausgeführt. Dies wird als Prozessvariable bezeichnet , und wir werden später sehen, wie sie festgelegt werden

Wir können zwar Prozessdefinitionsdateien in jedem Texteditor erstellen, dies ist jedoch nicht immer der bequemste Weg. Glücklicherweise bietet Flowable auch Optionen für die Benutzeroberfläche, um dies entweder mit einem Eclipse-Plugin oder einer Webanwendung zu tun. Wenn Sie stattdessen IntelliJ verwenden, ist auch ein IntelliJ-Plugin verfügbar.

4. Arbeiten mit Flowable API

Nachdem wir unseren einfachen Prozess in einer XML-Datei gemäß dem BPMN 2.0-Standard definiert haben, benötigen wir eine Möglichkeit, ihn einzureichen und auszuführen. Flowable bietet die Process Engine-API für die Interaktion mit Flowable Engines . Flowable ist sehr flexibel und bietet verschiedene Möglichkeiten zur Bereitstellung dieser API.

Da Flowable eine Java-API ist, können wir die Prozess-Engine in jede Java-Anwendung aufnehmen, indem wir einfach die erforderlichen JAR-Dateien einfügen. Wir können Maven sehr gut für die Verwaltung dieser Abhängigkeiten nutzen.

Darüber hinaus enthält Flowable gebündelte APIs für die Interaktion mit Flowable über HTTP. Wir können diese APIs verwenden, um so ziemlich alles zu tun, was sonst über Flowable API möglich ist.

Schließlich bietet Flowable eine hervorragende Unterstützung für die Integration in Spring und Spring Boot! In unserem Tutorial werden wir die Integration von Flowable und Spring Boot verwenden.

5. Erstellen einer Demo-Anwendung mit Process Engine

Lassen Sie uns nun eine einfache Anwendung erstellen, die eine Prozess-Engine aus Flowable umschließt und eine HTTP-basierte API für die Interaktion mit der Flowable-API bietet. Es kann auch eine Web- oder mobile Anwendung über der API vorhanden sein, um die Erfahrung zu verbessern, aber wir werden dies für dieses Tutorial überspringen.

Wir erstellen unsere Demo als Spring Boot-Anwendung.

5.1. Abhängigkeiten

Lassen Sie uns zunächst die Abhängigkeiten sehen, die wir aus Maven ziehen müssen:

 org.springframework.boot spring-boot-starter-web   org.flowable flowable-spring-boot-starter 6.4.1   com.h2database h2 runtime 

Die von uns benötigten Abhängigkeiten sind alle bei Maven Central verfügbar:

  • Spring Boot Starter für Web - Dies ist ein Standardstarter für Spring Boot
  • Flowable Starter für Spring Boot - Dies ist für Flow Boot-Motoren erforderlich
  • H2-Datenbank - Flowable erfordert eine Datenbank zum Speichern von Daten, und H2 ist die Standarddatenbank im Speicher

5.2. Prozessdefinition

Wenn wir unsere Spring Boot-Anwendung starten, versucht sie automatisch, alle Prozessdefinitionen zu laden, die im Ordner "Ressourcen / Prozesse" vorhanden sind. Erstellen Sie daher eine XML-Datei mit der oben erstellten Prozessdefinition mit dem Namen "article-workflow.bpmn20.xml" und legen Sie sie in diesem Ordner ab.

5.3. Konfigurationen

Da wir wissen, dass Spring Boot bei der Anwendungskonfiguration einen sehr einfühlsamen Ansatz verfolgt, gilt dies auch für Flowable als Teil von Spring Boot. Zum Beispiel H2 als einzigen Datenbanktreiber auf dem Classpath Erkennung Flowable konfiguriert sie automatisch für die Verwendung .

Offensichtlich kann jeder konfigurierbare Aspekt über Anwendungseigenschaften auf benutzerdefinierte Weise konfiguriert werden. In diesem Tutorial bleiben wir jedoch bei den Standardeinstellungen!

5.4. Java-Delegierte

In our process definition, we've used a couple of Java classes that are supposed to be invoked as parts of service tasks. These classes implement the JavaDelegate interface and are known as Java Delegates in Flowable. We'll now define dummy classes for these Java Delegates:

public class PublishArticleService implements JavaDelegate { public void execute(DelegateExecution execution) { System.out.println("Publishing the approved article."); } }
public class SendMailService implements JavaDelegate { public void execute(DelegateExecution execution) { System.out.println("Sending rejection mail to author."); } }

Obviously, we must replace these dummy classes with actual services to publish an article or send an email.

5.5. HTTP APIs

Finally, let's create some endpoints to interact with the process engine and work with the process we've defined.

We'll begin by defining a controller exposing three endpoints:

@RestController public class ArticleWorkflowController { @Autowired private ArticleWorkflowService service; @PostMapping("/submit") public void submit(@RequestBody Article article) { service.startProcess(article); } @GetMapping("/tasks") public List getTasks(@RequestParam String assignee) { return service.getTasks(assignee); } @PostMapping("/review") public void review(@RequestBody Approval approval) { service.submitReview(approval); } }

Our controller exposes endpoints to submit an article for review, fetch a list of articles to review, and finally, to submit a review for an article. Article and Approval are standard POJOs that can be found in the repository.

We are actually delegating most of the work to ArticleWorkflowService:

@Service public class ArticleWorkflowService { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Transactional public void startProcess(Article article) { Map variables = new HashMap(); variables.put("author", article.getAuthor()); variables.put("url", article.getUrl()); runtimeService.startProcessInstanceByKey("articleReview", variables); } @Transactional public List getTasks(String assignee) { List tasks = taskService.createTaskQuery() .taskCandidateGroup(assignee) .list(); return tasks.stream() .map(task -> { Map variables = taskService.getVariables(task.getId()); return new Article(task.getId(), (String) variables.get("author"), (String) variables.get("url")); }) .collect(Collectors.toList()); } @Transactional public void submitReview(Approval approval) { Map variables = new HashMap(); variables.put("approved", approval.isStatus()); taskService.complete(approval.getId(), variables); } }

Now, most of the code here is pretty intuitive, but let's understand the salient points:

  • RuntimeService to instantiate the process for a particular submission
  • TaskService to query and update tasks
  • Wrapping all database calls in transactions supported by Spring
  • Storing details like author and URL, among others, in a Map, and saving with the process instance; these are known as process variables, and we can access them within a process definition, as we saw earlier

Now, we're ready to test our application and process engine. Once we start the application, we can simply use curl or any REST client like Postman to interact with the endpoints we've created.

6. Unit Testing Processes

Flowable supports different versions of JUnit, including JUnit 5, for creating unit tests for business processes. Flowable integration with Spring has suitable support for this as well. Let's see a typical unit test for a process in Spring:

@ExtendWith(FlowableSpringExtension.class) @ExtendWith(SpringExtension.class) public class ArticleWorkflowUnitTest { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Test @Deployment(resources = { "processes/article-workflow.bpmn20.xml" }) void articleApprovalTest() { Map variables = new HashMap(); variables.put("author", "[email protected]"); variables.put("url", "//baeldung.com/dummy"); runtimeService.startProcessInstanceByKey("articleReview", variables); Task task = taskService.createTaskQuery().singleResult(); assertEquals("Review the submitted tutorial", task.getName()); variables.put("approved", true); taskService.complete(task.getId(), variables); assertEquals(0, runtimeService.createProcessInstanceQuery().count()); } }

This should pretty much look like a standard unit test in Spring, except for few annotations like @Deployment. Now, the @Deployment annotation is provided by Flowable to create and delete a process deployment around test methods.

7. Understanding the Deployment of Processes

While we'll not cover the details of process deployment in this tutorial, it is worthwhile to cover some aspects that are of importance.

Typically, processes are archived as Business Archive (BAR) and deployed in an application. While being deployed, this archive is scanned for artifacts — like process definitions — and processed. You may have noticed the convention of the process definition file ending with “.bpmn20.xml”.

While we've used the default in-memory H2 database in our tutorial, this actually cannot be used in a real-world application, for the simple reason that an in-memory database will not retain any data across start-ups and is practically impossible to use in a clustered environment! Hence, we must use a production-grade relational database and provide the required configurations in the application.

While BPMN 2.0 itself does not have any notion of versioning, Flowable creates a version attribute for the process, which is deployed in the database. If an updated version of the same process, as identified by the attribute “id”, is deployed, a new entry is created with the version being incremented. When we try to start a process by “id”, the process engine fetches the latest version of the process definition deployed.

If we use one of the designers we discussed earlier to create the process definition, we already have a visualization for our process. We can export the process diagram as an image and place it alongside the XML process definition file. If we stick to the standard naming convention suggested by Flowable, this image will be processed by the process engine along with the process itself. Moreover, we can fetch this image through APIs as well!

8. Browsing History of Process Instances

It is often of key importance in the case of business processes to understand what happened in the past. We may need this for simple debugging or complex legal auditing purposes.

Flowable records what happens through the process execution and keeps it in the database. Moreover, Flowable makes this history available through APIs to query and analyze. There are six entities under which Flowable records these, and the HistoryService has methods to query them all.

Let's see a simple query to fetch finished process instances:

HistoryService historyService = processEngine.getHistoryService(); List activities = historyService .createHistoricActivityInstanceQuery() .processInstanceId(processInstance.getId()) .finished() .orderByHistoricActivityInstanceEndTime() .asc() .list();

As we can see, the API to query recorded data is pretty composable. In this example, we're querying finished process instances by ID and ordering them in ascending order of their end time.

9. Monitoring Processes

Monitoring is a key aspect of any business-critical application, and even more so for an application handling business processes of an organization. Flowable has several options to let us monitor processes in real time.

Flowable provides specific MBeans that we can access over JMX, to not only gather data for monitoring but to perform many other activities as well. We can integrate this with any standard JMX client, including jconsole, which is present alongside standard Java distributions.

Using JMX for monitoring opens a lot of options but is relatively complex and time-consuming. However, since we're using Spring Boot, we're in luck!

Spring Boot offers Actuator Endpoints to gather application metrics over HTTP. We can seamlessly integrate this with a tool stack like Prometheus and Grafana to create a production-grade monitoring tool with minimal effort.

Flowable provides an additional Actuator Endpoint exposing information about the running processes. This is not as good as gathering information through JMX, but it is quick, easy and, most of all, sufficient.

10. Conclusion

In this tutorial, we discussed business processes and how to define them in the BPMN 2.0 standard. Then, we discussed the capabilities of Flowable process engine and APIs to deploy and execute processes. We saw how to integrate this in a Java application, specifically in Spring Boot.

Weiter haben wir andere wichtige Aspekte von Prozessen wie deren Bereitstellung, Visualisierung und Überwachung besprochen. Natürlich haben wir gerade die Oberfläche des Geschäftsprozesses und eine leistungsstarke Engine wie Flowable zerkratzt. Flowable verfügt über eine sehr umfangreiche API mit ausreichender Dokumentation. Dieses Tutorial hätte jedoch unser Interesse an dem Thema wecken sollen!

Wie immer ist der Code für die Beispiele auf GitHub verfügbar.