Introducción a Flowable

1. Información general

Flowable es un motor de procesos de negocio escrito en Java. En este tutorial, repasaremos los detalles de los procesos comerciales y comprenderemos cómo podemos aprovechar la API de Java Flowable para crear e implementar un proceso comercial de muestra.

2. Comprensión de los procesos comerciales

En pocas palabras, un proceso de negocio es un conjunto de tareas que, una vez completadas en un orden definido, logran un objetivo definido . Cada tarea en un proceso empresarial tiene entradas y salidas claramente definidas. Estas tareas pueden requerir la intervención humana o pueden estar completamente automatizadas.

OMG (Object Management Group) ha definido un estándar llamado Business Process Model and Notation (BPMN) para que las empresas definan y comuniquen sus procesos . BPMN ha recibido un amplio apoyo y aceptación en la industria. La API Flowable es totalmente compatible con la creación y la implementación de definiciones de proceso BPMN 2.0.

3. Creación de definiciones de procesos

Supongamos que tenemos un proceso simple para revisar el artículo antes de publicarlo.

La esencia de este proceso es que los autores envían un artículo y los editores lo aceptan o lo rechazan. Si es aceptado, el artículo se publica inmediatamente; sin embargo, si se rechaza, se notifica al autor por correo electrónico:

Creamos definiciones de procesos como archivos XML utilizando el estándar XML BPMN 2.0.

Definamos nuestro proceso simple según el estándar BPMN 2.0:

Ahora bien, hay una gran cantidad de elementos aquí que son elementos XML estándar, mientras que otros son específicos de BPMN 2.0:

  • El proceso entero se envuelve en una etiqueta llamada “proceso”, que a su vez, es parte de una etiqueta llamada “Definiciones”
  • Un proceso consta de eventos, flujos, tareas y puertas de enlace.
  • Un evento es un evento de inicio o un evento de finalización
  • Un flujo (en este ejemplo, un flujo de secuencia) conecta otros elementos como eventos y tareas
  • Las tareas son donde se realiza el trabajo real; estas pueden ser "tareas de usuario" o "tareas de servicio", entre otras
  • Una tarea de usuario requiere que un usuario humano interactúe con la API Flowable y tome medidas
  • Una tarea de servicio representa una tarea automática, que puede ser una llamada a una clase Java o incluso una llamada HTTP.
  • Una pasarela se ejecuta basándose en el atributo "aprobado"; esto se conoce como una variable de proceso , y veremos cómo configurarlas más adelante

Si bien podemos crear archivos de definición de procesos en cualquier editor de texto, esta no siempre es la forma más conveniente. Sin embargo, afortunadamente, Flowable también viene con opciones de interfaz de usuario para hacer esto usando un complemento de Eclipse o una aplicación web. Si está utilizando IntelliJ en su lugar, también hay un complemento IntelliJ disponible.

4. Trabajar con API fluida

Ahora que hemos definido nuestro proceso simple en un archivo XML según el estándar BPMN 2.0, necesitamos una forma de enviarlo y ejecutarlo. Flowable proporciona la API de Process Engine para interactuar con Flowable Engines . Flowable es muy flexible y ofrece varias formas de implementar esta API.

Dado que Flowable es una API de Java, podemos incluir el motor de procesos en cualquier aplicación de Java simplemente incluyendo los archivos JAR necesarios. Podemos aprovechar Maven para administrar estas dependencias.

Además, Flowable viene con API empaquetadas para interactuar con Flowable a través de HTTP. Podemos usar estas API para hacer prácticamente cualquier otra cosa a través de la API fluida.

¡Finalmente, Flowable tiene un excelente soporte para la integración con Spring y Spring Boot! Usaremos la integración Flowable y Spring Boot en nuestro tutorial.

5. Creación de una aplicación de demostración con Process Engine

Creemos ahora una aplicación simple que envuelve un motor de procesos de Flowable y ofrece una API basada en HTTP para interactuar con la API de Flowable. También puede haber una aplicación web o móvil encima de la API para mejorar la experiencia, pero lo omitiremos en este tutorial.

Crearemos nuestra demostración como una aplicación Spring Boot.

5.1. Dependencias

Primero, veamos las dependencias que necesitamos extraer de Maven:

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

Las dependencias que requerimos están todas disponibles en Maven Central:

  • Spring Boot Starter para Web: este es un iniciador estándar para Spring Boot
  • Arrancador fluido para Spring Boot: esto es necesario para motores Spring Boot Flowable
  • Base de datos H2: Flowable requiere una base de datos para almacenar datos y H2 es la base de datos en memoria predeterminada

5.2. Definición de proceso

Cuando iniciamos nuestra aplicación Spring Boot, intenta cargar automáticamente todas las definiciones de proceso presentes en la carpeta "recursos / procesos". Por lo tanto, creemos un archivo XML con la definición de proceso que creamos anteriormente, con el nombre “article-workflow.bpmn20.xml”, y colóquelo en esa carpeta.

5.3. Configuraciones

Como sabemos que Spring Boot adopta un enfoque muy obstinado hacia la configuración de aplicaciones, eso también se aplica a Flowable como parte de Spring Boot. Por ejemplo, al detectar H2 como el único controlador de base de datos en la ruta de clase, Flowable lo configura automáticamente para su uso .

Evidentemente, todos los aspectos configurables se pueden configurar de forma personalizada a través de las propiedades de la aplicación. ¡Para este tutorial, sin embargo, nos ceñiremos a los valores predeterminados!

5.4. Delegados de 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, discutimos otros aspectos importantes de los procesos como su implementación, visualización y monitoreo. No hace falta decir que acabamos de arañar la superficie del proceso empresarial y un motor potente como Flowable. Flowable tiene una API muy rica con suficiente documentación disponible. ¡Este tutorial, sin embargo, debería haber despertado nuestro interés en el tema!

Como siempre, el código de los ejemplos está disponible en GitHub.