REUNICO | Разработка и сопровождение ПО: Camunda для разработчика - Часть 4

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.

Camunda для разработчика: Работа с базой данных
  • Персистентный слой - сущности и репозитории. Первые являются "отражением" ваших бизнес-данных (представленных в табличках реляционной СУБД) в виде объектов 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

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

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

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

Camunda: Процесс обработки запросов на предоставление доступа

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

  • 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