Introduzione a Flowable

1. Panoramica

Flowable è un motore di processi aziendali scritto in Java. In questo tutorial, esamineremo i dettagli dei processi aziendali e capiremo come possiamo sfruttare l'API Java Flowable per creare e distribuire un processo aziendale di esempio.

2. Comprensione dei processi aziendali

In poche parole, un processo aziendale è un insieme di attività che, una volta completate in un ordine definito, raggiunge un obiettivo definito . Ogni attività in un processo aziendale ha input e output chiaramente definiti. Queste attività possono richiedere l'intervento umano o possono essere completamente automatizzate.

OMG (Object Management Group) ha definito uno standard chiamato Business Process Model and Notation (BPMN) per consentire alle aziende di definire e comunicare i propri processi . BPMN è diventato ampiamente supportato e accettato nel settore. L'API Flowable supporta completamente la creazione e la distribuzione delle definizioni di processo BPMN 2.0.

3. Creazione di definizioni di processo

Supponiamo di avere un semplice processo per la revisione dell'articolo prima della pubblicazione.

L'essenza di questo processo è che gli autori inviano un articolo e gli editori lo accettano o lo rifiutano. Se accettato, l'articolo viene pubblicato immediatamente; tuttavia, se rifiutato, l'autore viene avvisato tramite email:

Creiamo definizioni di processo come file XML utilizzando lo standard XML BPMN 2.0.

Definiamo il nostro semplice processo secondo lo standard BPMN 2.0:

Ora, ci sono un certo numero di elementi qui che sono roba XML standard, mentre altri sono specifici per BPMN 2.0:

  • L' intero processo è racchiuso in un tag chiamato "processo", che a sua volta fa parte di un tag chiamato "definizioni"
  • Un processo è costituito da eventi, flussi, attività e gateway
  • Un evento è un evento di inizio o un evento di fine
  • Un flusso (in questo esempio, un flusso di sequenza) collega altri elementi come eventi e attività
  • Le attività sono dove viene svolto il lavoro effettivo; queste possono essere "attività dell'utente" o "attività di servizio", tra le altre
  • Un'attività utente richiede che un utente umano interagisca con l'API Flowable e agisca
  • Un'attività di servizio rappresenta un'attività automatica, che può essere una chiamata a una classe Java o anche una chiamata HTTP
  • Un gateway viene eseguito in base all'attributo "approvato"; questa è nota come variabile di processo e vedremo come impostarle in seguito

Sebbene possiamo creare file di definizione del processo in qualsiasi editor di testo, questo non è sempre il modo più conveniente. Fortunatamente, tuttavia, Flowable include anche opzioni dell'interfaccia utente per farlo utilizzando un plug-in Eclipse o un'applicazione Web. Se invece utilizzi IntelliJ, è disponibile anche un plug-in IntelliJ.

4. Lavorare con Flowable API

Ora che abbiamo definito il nostro semplice processo in un file XML secondo lo standard BPMN 2.0, abbiamo bisogno di un modo per inviarlo ed eseguirlo. Flowable fornisce l'API di Process Engine per interagire con Flowable Engines . Flowable è molto flessibile e offre diversi modi per distribuire questa API.

Dato che Flowable è un'API Java, possiamo includere il motore del processo in qualsiasi applicazione Java semplicemente includendo i file JAR richiesti. Possiamo benissimo sfruttare Maven per la gestione di queste dipendenze.

Inoltre, Flowable viene fornito con API in bundle per interagire con Flowable su HTTP. Possiamo utilizzare queste API per fare praticamente qualsiasi cosa altrimenti possibile tramite Flowable API.

Infine, Flowable ha un eccellente supporto per l'integrazione con Spring e Spring Boot! Faremo uso dell'integrazione Flowable e Spring Boot nel nostro tutorial.

5. Creazione di un'applicazione demo con Process Engine

Creiamo ora una semplice applicazione che avvolge un motore di processo da Flowable e offre un'API basata su HTTP per interagire con l'API Flowable. Potrebbe anche esserci un'applicazione web o mobile che si trova sopra l'API per migliorare l'esperienza, ma la salteremo per questo tutorial.

Creeremo la nostra demo come applicazione Spring Boot.

5.1. Dipendenze

Per prima cosa, vediamo le dipendenze che dobbiamo estrarre da Maven:

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

Le dipendenze di cui abbiamo bisogno sono tutte disponibili su Maven Central:

  • Spring Boot Starter per Web: è un antipasto standard per Spring Boot
  • Flowable Starter per Spring Boot - necessario per i motori Spring Boot Flowable
  • Database H2 - Flowable richiede un database per memorizzare i dati e H2 è il database in memoria predefinito

5.2. Definizione del processo

Quando avviamo la nostra applicazione Spring Boot, cerca di caricare automaticamente tutte le definizioni di processo presenti nella cartella "risorse / processi". Pertanto, creiamo un file XML con la definizione del processo che abbiamo creato sopra, con il nome "article-workflow.bpmn20.xml", e posizioniamolo in quella cartella.

5.3. Configurazioni

Poiché sappiamo che Spring Boot adotta un approccio altamente supponente nei confronti della configurazione dell'applicazione, ciò vale anche per Flowable come parte di Spring Boot. Ad esempio, rilevando H2 come l'unico driver di database sul classpath, Flowable lo configura automaticamente per l'uso .

Ovviamente ogni aspetto configurabile può essere configurato in maniera personalizzata tramite le proprietà dell'applicazione. Per questo tutorial, tuttavia, ci atterremo alle impostazioni predefinite!

5.4. Delegati Java

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.

Continuando ulteriormente, abbiamo discusso altri importanti aspetti dei processi come la loro distribuzione, visualizzazione e monitoraggio. Inutile dire che abbiamo appena scalfito la superficie del processo aziendale e un potente motore come Flowable. Flowable ha un'API molto ricca con documentazione sufficiente disponibile. Questo tutorial, tuttavia, dovrebbe aver stuzzicato il nostro interesse per l'argomento!

Come sempre, il codice per gli esempi è disponibile su GitHub.