Найти тему
REUNICO

Camunda для разработчика - Часть 4

Коллеги, изучающие Camunda BPM, периодически просят рассказать, каким образом система работает с базой данных? Я бы предпочел переформулировать этот вопрос, изложив его так: "Как Camunda взаимодействует с бизнес-данными?"

Из числа наиболее популярных способов можно упомянуть следующие:

  • Синхронные REST/SOAP-вызовы через Java Delegate или HTTP/SOAP-connector;
  • Отправка (получение) сообщения в (из) брокера очереди (ActiveMQ, Rabbit MQ, Kafka, IBM MQ) - через Java Delegate;
  • Получение/предоставление данных как переменных процесса через REST API;
  • Работа с JPA/ORM через Java Delegate;
  • Также, гораздо реже можно встретить извлечение данных непосредственно через JDBC (опять же, при помощи делегатов).

В сегодняшней статье речь пойдет о предпоследнем способе, предполагающем использование Spring Data JPA и популярной встраиваемой СУБД H2. Подробности под катом.

Информация, рассматриваемая в настоящей статье:

  • Структура приложения Camunda Spring Boot;
  • Создание нового приложения Spring Boot;
  • Добавление зависимостей Camunda;
  • Добавление минимального набора properties;
  • Моделирование процесса;
  • Создание бизнес-сущности, репозитория, сервиса, делегатов;
  • Внесение изменений в модель процесса.

На картинке ниже приведено содержимое типичного приложения Camunda Spring Boot.

Архитектура приложения
Архитектура приложения
  • Персистентный слой - сущности и репозитории. Первые являются "отражением" ваших бизнес-данных (представленных в табличках реляционной СУБД) в виде объектов Java (POJO). Вторые являются интерфейсами, предоставляющими набор методов для работы с этими объектами (find(), save(), delete() и т.д.).
  • Сервисы - бизнес-логика приложения, спрятанная в атомарных компонентах - сервис для работы с документами, сервис для работы с платежами и т.д;
  • Контроллеры - если ваше приложение имеет интерфейсы к внешним системам или веб-интерфейс, то контроллеры - это то, что обеспечивает необходимое представление данных (формирует HTML, PDF, JSON, XML и т.д.), выдавая их в сервис-потребитель, SPA или напрямую в браузер. Следуя лучшим практикам, контроллер должен быть максимально "тупым" - вызвать нужный метод и вернуть данные;
  • Java Delegates, Listeners - компоненты, используемые в качестве посредников между движком BPM и вашими сервисами. Образно говоря, если приложение это машина, то делагаты - это руль, педали и рычаг переключения передач, посредством которых Camunda управляет приложением. Аналогично контроллерам, делегаты не должны содержать бизнес-логику. Их задача - извлечение/запись переменных процесса и вызов нужных методов.

Итак, начнем с создания пустого приложения Spring Boot. Нам понадобится Spring Initializr, доступный на сайте https://start.spring.io. Также можно использовать инциализатор, встроенный в InteliJ IDEA. Необходимо задать параметры проекта и добавить зависимости:

  • Spring Web;
  • Spring JPA;
  • H2;

Полученный zip-файл необходимо раскрыть в проект (если генерируете из IDEA, она развернет его автоматически). Следующий шаг - открыть файл pom.xml и добавить зависимости Camunda:

<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
<version>7.13.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
<version>7.13.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
<version>7.13.0</version>
</dependency>

Переименуем файл main/resources/application.properties в application.yml и заполним его следующими настройками (обратите внимание на отступы!!!):

spring:
datasource:
url: jdbc:h2:file:./target/h2db/db/access;DB_CLOSE_DELAY=-1
username: access
password:
driver-class: org.h2.Driver
h2:
console:
enabled: true
path: /h2
jpa:
hibernate:
ddl-auto: update
camunda:
bpm:
admin-user:
password: demo
id: demo
first-name: Demo
last-name: Demo
email: info@reunico.com

Оставим пока в покое печенегов и половцев и рассмотрим какой-то более приближенный к реальности процесс. Например, у нас есть необходимость предоставлять пользователям (согласно их запросу) доступ к закрытой информации. Например:

  • Пользователь на сайте заполняет форму, указывая идентификатор нужной информации и обоснование запроса;
  • В базе создается запись - запрос доступа;
  • Ответственный сотрудник рассматривает запрос и принимает решение - предоставить доступ или нет;
  • Запись о решении сохраняется в базу и в дальнейшем (если оно положительное) может использоваться для предоставления доступа.

Смоделируем процесс следующего вида:

-2

Далее необходимо реализовать классы:

  • AccessRequest - бизнес-объект, запись о запросе предоставления доступа;
  • AccessRequestRepository - интерфейс-репозиторий, обеспечивающий CRUD-операции с записями AccessRequest;
  • AccessRequestService - сервис с методами: create() и update();
  • Делегаты CreateAccessRequest (вызов create()) и UpdateAccessRequest (вызов update()).

Указанные делегаты необходимо прописать в качестве Delegate Expression в сервисных задачах Сохранить запрос в базе и Обновить запрос в базе. Полный листинг проекта приведен на GitHub: https://github.com/Reunico/camunda-db-example.

Презентации проекта на GitHub: Reunico Camunda Presentations

Актуальные статьи по Camunda:

7 причин перейти на Camunda Enterprise

Локализация Camunda Tasklist

Маршрутизация событий в процессах

Все, что вы хотели знать о Camunda, но боялись спросить