Въведение в Flowable

1. Общ преглед

Flowable е двигател за бизнес процеси, написан на Java. В този урок ще разгледаме подробностите за бизнес процесите и ще разберем как можем да използваме API на Flowable Java за създаване и внедряване на примерен бизнес процес.

2. Разбиране на бизнес процесите

Просто казано, бизнес процес е набор от задачи, които, след като бъдат завършени в определен ред, постигат определена цел . Всяка задача в бизнес процеса има ясно дефинирани входове и изходи. Тези задачи може да изискват човешка намеса или могат да бъдат напълно автоматизирани.

OMG (Object Management Group) дефинира стандарт, наречен Business Process Model and Notation (BPMN), за да могат бизнесът да дефинира и съобщава своите процеси . BPMN стана широко подкрепен и приет в индустрията. API на Flowable напълно поддържа създаването и внедряването на дефиниции на процеса BPMN 2.0.

3. Създаване на дефиниции на процеса

Да предположим, че имаме лесен процес за преглед на статията преди публикуването.

Същността на този процес е, че авторите изпращат статия, а редакторите я приемат или отхвърлят. Ако бъде прието, статията се публикува незабавно; ако обаче бъде отхвърлен, авторът се уведомява по имейл:

Създаваме дефиниции на процеси като XML файлове, използвайки стандарта BPMN 2.0 XML.

Нека дефинираме нашия прост процес съгласно стандарта BPMN 2.0:

Сега има доста на брой елементи, които са стандартни XML неща, докато други са специфични за BPMN 2.0:

  • В целия процес е обвито в маркер, наречен "процес", който от своя страна е част от маркер, наречен "дефиниции"
  • Процесът се състои от събития, потоци, задачи и шлюзове
  • Събитието е или начално събитие, или крайно събитие
  • Поток (в този пример поток на последователност) свързва други елементи като събития и задачи
  • Задачите са там, където се извършва действителната работа; това могат да бъдат „потребителски задачи“ или „сервизни задачи“, наред с други
  • Потребителска задача изисква човешки потребител да взаимодейства с API на Flowable и да предприеме действия
  • Задача за услуга представлява автоматична задача, която може да бъде повикване към Java клас или дори HTTP повикване
  • Шлюз се изпълнява въз основа на атрибута „одобрен“; това е известно като променлива на процеса и ще видим как да ги зададем по-късно

Въпреки че можем да създаваме файлове за дефиниция на процеси във всеки текстов редактор, това не винаги е най-удобният начин. За щастие обаче Flowable се предлага и с опции за потребителски интерфейс, за да се направи това с помощта на приставка Eclipse или уеб приложение. Ако вместо това използвате IntelliJ, има и плъгин IntelliJ.

4. Работа с Flowable API

Сега, когато дефинирахме нашия прост процес в XML файл съгласно стандарта BPMN 2.0, имаме нужда от начин да го изпратим и стартираме. Flowable предоставя API на Process Engine за взаимодействие с Flowable Engines . Flowable е много гъвкав и предлага няколко начина за внедряване на този API.

Като се има предвид, че Flowable е Java API, можем да включим процесорния механизъм във всяко приложение на Java, като просто включим необходимите JAR файлове. Много добре можем да използваме Maven за управление на тези зависимости.

Освен това Flowable се предлага с включени API за взаимодействие с Flowable през HTTP. Можем да използваме тези приложни програмни интерфейси, за да направим почти всичко, което иначе е възможно, чрез Flowable API.

И накрая, Flowable има отлична поддръжка за интеграция с Spring и Spring Boot! Ще използваме интеграцията на Flowable и Spring Boot в нашия урок.

5. Създаване на демо приложение с Process Engine

Нека сега създадем просто приложение, което обгръща процесния двигател от Flowable и предлага API, базиран на HTTP, за взаимодействие с Flowable API. Възможно е да има уеб или мобилно приложение, което седи върху API, за да подобри практическата работа, но ще пропуснем това за този урок.

Ще създадем нашата демонстрация като приложение Spring Boot.

5.1. Зависимости

Първо, нека видим зависимостите, които трябва да извлечем от Maven:

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

Изискваните от нас зависимости са налични в Maven Central:

  • Spring Boot Starter за уеб - това е стандартен стартер за Spring Boot
  • Течащ стартер за пролетно зареждане - това е необходимо за пролетни двигатели с пролетно зареждане
  • H2 база данни - Flowable изисква база данни за съхранение на данни, а H2 е базата данни по подразбиране в паметта

5.2. Определение на процеса

Когато стартираме нашето приложение Spring Boot, то се опитва автоматично да зареди всички дефиниции на процеси, намиращи се в папката „ресурси / процеси“. Затова нека създадем XML файл с дефиницията на процеса, която създадохме по-горе, с името „article-workflow.bpmn20.xml“, и го поставим в тази папка.

5.3. Конфигурации

Тъй като сме наясно, че Spring Boot възприема силно самоуверен подход към конфигурацията на приложението, това важи и за Flowable като част от Spring Boot. Например, откривайки H2 като единствения драйвер за база данни в пътя на класа, Flowable автоматично го конфигурира за използване .

Очевидно всеки аспект, който може да се конфигурира, може да бъде конфигуриран по персонализиран начин чрез свойствата на приложението. За този урок обаче ще се придържаме към настройките по подразбиране!

5.4. Делегати на 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.

Продължавайки по-нататък, обсъдихме други важни аспекти на процесите като тяхното внедряване, визуализация и наблюдение. Излишно е да казвам, че току-що надраскахме повърхността на бизнес процеса и мощен двигател като Flowable. Flowable има много богат API с достатъчно налична документация. Този урок обаче трябваше да предизвика интереса ни към темата!

Както винаги, кодът за примерите е достъпен в GitHub.