Перейти к основному содержимому

Введение в Flowable

· 11 мин. чтения

1. Обзор

Flowable — это движок бизнес-процессов, написанный на Java. В этом руководстве мы подробно рассмотрим бизнес-процессы и поймем, как мы можем использовать Flowable Java API для создания и развертывания примера бизнес-процесса.

2. Понимание бизнес-процессов

Проще говоря, бизнес-процесс — это набор задач, выполнение которых в определенном порядке приводит к достижению определенной цели . Каждая задача в бизнес-процессе имеет четко определенные входы и выходы. Эти задачи могут потребовать вмешательства человека или могут быть полностью автоматизированы.

OMG (Группа управления объектами) определила стандарт под названием «Модель и нотация бизнес-процессов» (BPMN) для предприятий, чтобы определять и сообщать о своих процессах . BPMN получила широкую поддержку и признание в отрасли. Flowable API полностью поддерживает создание и развертывание определений процессов BPMN 2.0.

3. Создание определений процессов

Предположим, у нас есть простой процесс проверки статьи перед публикацией.

Суть этого процесса в том, что авторы представляют статью, а редакторы либо принимают, либо отклоняют ее. В случае принятия статья публикуется немедленно; однако в случае отклонения автор уведомляется по электронной почте:

./004384353309e353e3351777074c1d60.png

Мы создаем определения процессов в виде файлов XML с использованием стандарта XML BPMN 2.0.

Давайте определим наш простой процесс в соответствии со стандартом BPMN 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
xmlns:flowable="http://flowable.org/bpmn"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://www.flowable.org/processdef">
<process id="articleReview"
name="A simple process for article review." isExecutable="true">
<startEvent id="start" />
<sequenceFlow sourceRef="start" targetRef="reviewArticle" />
<userTask id="reviewArticle" name="Review the submitted tutorial"
flowable:candidateGroups="editors" />
<sequenceFlow sourceRef="reviewArticle" targetRef="decision" />
<exclusiveGateway id="decision" />
<sequenceFlow sourceRef="decision" targetRef="tutorialApproved">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${approved}]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="decision" targetRef="tutorialRejected">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${!approved}]]>
</conditionExpression>
</sequenceFlow>
<serviceTask id="tutorialApproved" name="Publish the approved tutorial."
flowable:class="com.foreach.service.PublishArticleService" />
<sequenceFlow sourceRef="tutorialApproved" targetRef="end" />
<serviceTask id="tutorialRejected" name="Send out rejection email"
flowable:class="com.foreach.service.SendMailService" />
<sequenceFlow sourceRef="tutorialRejected" targetRef="end" />
<endEvent id="end" />
</process>
</definitions>

Теперь здесь есть довольно много элементов, которые являются стандартными элементами XML, в то время как другие специфичны для BPMN 2.0:

  • Весь процесс заключен в тег под названием «процесс», который, в свою очередь, является частью тега под названием «определения».
  • Процесс состоит из событий, потоков, задач и шлюзов.
  • Событие является либо начальным событием, либо конечным событием
  • Поток (в данном примере поток последовательности) соединяет другие элементы, такие как события и задачи.
  • Задачи — это то, где выполняется фактическая работа; это могут быть, среди прочего, «пользовательские задачи» или «сервисные задачи».
  • Пользовательская задача требует, чтобы пользователь-человек взаимодействовал с Flowable API и предпринимал действия.
  • Служебная задача представляет собой автоматическую задачу, которая может быть вызовом класса Java или даже HTTP-вызовом.
  • Шлюз выполняется на основе атрибута «утвержден»; это известно как переменная процесса , и мы увидим, как их установить позже.

Хотя мы можем создавать файлы определения процесса в любом текстовом редакторе, это не всегда самый удобный способ. К счастью, Flowable также поставляется с параметрами пользовательского интерфейса, позволяющими сделать это с помощью подключаемого модуля Eclipse или веб-приложения . Если вместо этого вы используете IntelliJ, также доступен плагин IntelliJ .

4. Работа с Flowable API

Теперь, когда мы определили наш простой процесс в XML-файле в соответствии со стандартом BPMN 2.0, нам нужен способ отправить и запустить его. Flowable предоставляет API Process Engine для взаимодействия с Flowable Engines . Flowable очень гибкий и предлагает несколько способов развертывания этого API.

Учитывая, что Flowable — это API Java, мы можем включить механизм обработки в любое приложение Java, просто включив необходимые файлы JAR. Мы можем очень хорошо использовать Maven для управления этими зависимостями.

Более того, Flowable поставляется со встроенными API для взаимодействия с Flowable через HTTP. Мы можем использовать эти API практически для всего, что возможно через Flowable API.

Наконец, Flowable отлично поддерживает интеграцию с Spring и Spring Boot! В нашем руководстве мы будем использовать интеграцию Flowable и Spring Boot.

5. Создание демонстрационного приложения с Process Engine

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

Мы создадим нашу демонстрацию как приложение Spring Boot.

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

Во-первых, давайте посмотрим, какие зависимости нам нужно извлечь из Maven:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.4.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

Все требуемые зависимости доступны в Maven Central:

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

Когда мы запускаем наше приложение Spring Boot, оно пытается автоматически загрузить все определения процессов, присутствующие в папке «resources/processes». Поэтому давайте создадим файл XML с определением процесса, которое мы создали выше, с именем «article-workflow.bpmn20.xml» и поместим его в эту папку.

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

Поскольку мы знаем, что Spring Boot использует очень самоуверенный подход к настройке приложения, это справедливо и для Flowable как части Spring Boot. Например, обнаружив H2 как единственный драйвер базы данных в пути к классам, Flowable автоматически настраивает его для использования .

Очевидно, что каждый настраиваемый аспект можно настроить по-своему через свойства приложения . Однако для этого урока мы будем придерживаться значений по умолчанию!

5.4. Делегаты Java

В нашем определении процесса мы использовали пару классов Java, которые должны вызываться как часть служебных задач. Эти классы реализуют интерфейс JavaDelegate и известны как делегаты Java в Flowable . Теперь мы определим фиктивные классы для этих делегатов Java:

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.");
}
}

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

5.5. HTTP-API

Наконец, давайте создадим несколько конечных точек для взаимодействия с обработчиком процессов и работы с определенным нами процессом.

Мы начнем с определения контроллера, предоставляющего три конечные точки:

@RestController
public class ArticleWorkflowController {
@Autowired
private ArticleWorkflowService service;

@PostMapping("/submit")
public void submit(@RequestBody Article article) {
service.startProcess(article);
}

@GetMapping("/tasks")
public List<Article> getTasks(@RequestParam String assignee) {
return service.getTasks(assignee);
}

@PostMapping("/review")
public void review(@RequestBody Approval approval) {
service.submitReview(approval);
}
}

Наш контроллер предоставляет конечные точки для отправки статьи на рецензирование, получения списка статей для рецензирования и, наконец, отправки рецензии на статью. Статья и одобрение — это стандартные POJO, которые можно найти в репозитории.

На самом деле мы делегируем большую часть работы ArticleWorkflowService :

@Service
public class ArticleWorkflowService {
@Autowired
private RuntimeService runtimeService;

@Autowired
private TaskService taskService;

@Transactional
public void startProcess(Article article) {
Map<String, Object> variables = new HashMap<>();
variables.put("author", article.getAuthor());
variables.put("url", article.getUrl());
runtimeService.startProcessInstanceByKey("articleReview", variables);
}

@Transactional
public List<Article> getTasks(String assignee) {
List<Task> tasks = taskService.createTaskQuery()
.taskCandidateGroup(assignee)
.list();
return tasks.stream()
.map(task -> {
Map<String, Object> 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<String, Object> variables = new HashMap<String, Object>();
variables.put("approved", approval.isStatus());
taskService.complete(approval.getId(), variables);
}
}

Теперь большая часть кода здесь довольно интуитивно понятна, но давайте разберемся с основными моментами:

  • RuntimeService для создания экземпляра процесса для конкретной отправки
  • TaskService для запроса и обновления задач
  • Обертывание всех вызовов базы данных в транзакциях, поддерживаемых Spring
  • Сохранение таких сведений, как автор и URL-адрес, среди прочего, на карте и сохранение с экземпляром процесса; они известны как переменные процесса, и мы можем получить к ним доступ в определении процесса , как мы видели ранее.

Теперь мы готовы протестировать наше приложение и механизм обработки. Как только мы запустим приложение, мы можем просто использовать curl или любой клиент REST, такой как Postman, для взаимодействия с созданными нами конечными точками.

6. Процессы модульного тестирования

Flowable поддерживает различные версии JUnit, включая JUnit 5, для создания модульных тестов для бизнес-процессов. Потоковая интеграция со Spring также имеет подходящую поддержку для этого. Давайте посмотрим на типичный модульный тест для процесса в 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<String, Object> variables = new HashMap<>();
variables.put("author", "test@foreach.com");
variables.put("url", "http://foreach.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());
}
}

Это должно выглядеть как стандартный модульный тест в Spring, за исключением нескольких аннотаций, таких как @Deployment . Теперь Flowable предоставляет аннотацию @Deployment для создания и удаления развертывания процесса вокруг методов тестирования.

7. Понимание развертывания процессов

Хотя в этом руководстве мы не будем рассматривать детали развертывания процессов, стоит рассмотреть некоторые важные аспекты.

Обычно процессы архивируются как бизнес-архив (BAR) и развертываются в приложении . При развертывании этот архив сканируется на наличие артефактов, таких как определения процессов, и обрабатывается. Возможно, вы заметили соглашение о том, что файл определения процесса заканчивается на «.bpmn20.xml».

Хотя в нашем руководстве мы использовали базу данных H2 в памяти по умолчанию, ее на самом деле нельзя использовать в реальном приложении по той простой причине, что база данных в памяти не будет сохранять никаких данных при запуске и практически невозможно использовать в кластерной среде! Следовательно, мы должны использовать реляционную базу данных производственного уровня и предоставлять необходимые конфигурации в приложении .

В то время как в самой BPMN 2.0 нет понятия управления версиями, Flowable создает атрибут версии для процесса, который развертывается в базе данных . Если развернута обновленная версия того же процесса, что идентифицируется атрибутом «id», создается новая запись с увеличенной версией. Когда мы пытаемся запустить процесс по «id», механизм процесса получает последнюю версию развернутого определения процесса.

Если мы воспользуемся одним из конструкторов, которые мы обсуждали ранее, для создания определения процесса, у нас уже будет визуализация нашего процесса. Мы можем экспортировать диаграмму процесса в виде изображения и поместить ее вместе с XML-файлом определения процесса. Если мы будем придерживаться стандартного соглашения об именах, предложенного Flowable, это изображение будет обрабатываться механизмом процесса вместе с самим процессом. Более того, мы можем получить это изображение и через API!

8. Просмотр истории экземпляров процессов

Часто ключевое значение в случае бизнес-процессов имеет понимание того, что произошло в прошлом. Нам это может понадобиться для простой отладки или сложного юридического аудита.

Flowable записывает, что происходит во время выполнения процесса, и сохраняет его в базе данных. Более того, Flowable делает эту историю доступной через API для запроса и анализа. Есть шесть сущностей, в которых Flowable записывает их, и у HistoryService есть методы для запроса их всех.

Давайте посмотрим на простой запрос для получения завершенных экземпляров процесса:

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

Как мы видим, API для запроса записанных данных довольно компонуем. В этом примере мы запрашиваем завершенные экземпляры процесса по идентификатору и упорядочиваем их в порядке возрастания времени окончания.

9. Мониторинг процессов

Мониторинг является ключевым аспектом любого критически важного для бизнеса приложения, и тем более приложения, управляющего бизнес-процессами организации. Flowable имеет несколько опций, позволяющих нам отслеживать процессы в режиме реального времени.

Flowable предоставляет определенные MBeans, к которым мы можем получить доступ через JMX , не только для сбора данных для мониторинга, но и для выполнения многих других действий. Мы можем интегрировать это с любым стандартным клиентом JMX, включая jconsole , который присутствует вместе со стандартными дистрибутивами Java.

Использование JMX для мониторинга открывает множество возможностей, но является относительно сложным и требует много времени. Однако, поскольку мы используем Spring Boot, нам повезло!

Spring Boot предлагает конечные точки Actuator для сбора метрик приложений по HTTP. Мы можем легко интегрировать это со стеком инструментов, таким как Prometheus и Grafana , чтобы создать инструмент мониторинга производственного уровня с минимальными усилиями.

Flowable предоставляет дополнительную конечную точку Actuator, предоставляющую информацию о запущенных процессах. Это не так хорошо, как сбор информации через JMX, но это быстро, просто и, самое главное, достаточно.

10. Заключение

В этом руководстве мы обсудили бизнес-процессы и то, как их определить в стандарте BPMN 2.0. Затем мы обсудили возможности Flowable Process Engine и API для развертывания и выполнения процессов. Мы увидели, как интегрировать это в приложение Java, в частности, в Spring Boot.

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

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