Хабрахабр

Стильная, модная, молодежная разработка BPM на Camunda

image

BPM-разработка — дело непростое. Это обусловлено тем, что процесс должен быть читаемым и понятным заказчику, а не только корректным с технической точки зрения.

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

Ниже — о том, как эволюционировал этот подход и как менялись мы.
2018 год принципиально изменил наш подход к разработке бизнес-процессов.

Вместо пролога

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

К тому же эта платформа имеет довольно низкий порог входа, что позволяет начинающим разработчикам практически сразу погружаться в проект. IBM BPM — мощная платформа, которая включает богатый набор возможностей, таких как описание самих процессов, UI-форм, интеграционных модулей. Но есть у этого продукта и недостатки, которые если и не тормозят разработку, то уж точно не способствуют скорости и качеству:

  • Нет вменяемого контроля версий. IBM BPM просто не дает возможности нормально хранить процессы (код) в репозитории и использует свое собственное хранилище, которое не знает о таком понятии, как merge, например.
  • Разработка на Java 6. Возможно, на момент написания этой статьи уже можно разрабатывать на Java 7, но в 2019 году это слабое утешение.
  • IBM BPM крутится на WebSphere, в итоге разработчикам надо запасаться терпением при каждом обновлении своего модуля. К тому же это дополнительная головная боль для админов, которым периодически приходится возвращать к жизни этого монстра в случае его зависания.
  • Разработка интеграционных модулей в среде Integration Designer, которая в действительности является затюненным не в лучшую сторону Eclipse.
  • Нет нормальной возможности Unit-тестирования.
  • Высокая стоимость платформы.

Эти недостатки кроме чисто технического неудобства разработки породили еще одну проблему, которая, возможно, гораздо серьезнее всех вышеперечисленных. Во времена Java 12, Kotlin, микросервисов и прочих модных трендов и штук все эти нюансы очень демотивируют команду. Трудно испытывать радость при разработке в постоянно виснущем Integration Designer на Java 6 в 2019 году.

image

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

Было интересно попробовать этот новый язык, о котором слышали по большей части положительные отзывы. Так как его мы переписывали полностью, старого кода почти не было, мы могли практически ни в чем себя не ограничивать и поэтому в качестве языка разработки выбрали Kotlin. Финальный стек получился таким: Camunda, Spring Boot 2, Kotlin, Postgre. На некоторых других проектах в нашем отделе был успешный опыт внедрения.

Что это такое Camunda?

image

Она представляет собой набор библиотек, которые и позволяют выполнять описанные процессы. Camunda — это open-source-платформа для моделирования бизнес-процессов, которая написана на Java и в качестве языка разработки использует Java. Для хранения процессов можно выбрать in-memory или персистентную СУБД — в зависимости от задач. Для интеграции Camunda в проект достаточно добавить несколько зависимостей. По умолчанию платформа разворачивается на H2. Мы выбрали Postgre, так как нам важна история для «разбора полетов».

Чтобы из процесса вызвать java-код, достаточно реализовать интерфейс JavaDelegate, поднять этот Bean (можно указать делагат по полному имени, но через Bean удобнее и гибче) в контексте и указать его id на нужном шаге процесса. Разработка состоит из двух частей: создание flow-процесса в специальной утилите Camunda Modeler и написание java-кода, который обрабатывает шаги процесса, описанные на диаграмме. Логика работы делегатов довольно проста: что-то вычитали из контекста, выполнили какие-то действия и положили обратно в контекст. На Kotlin делегат выглядит еще более лаконично.

image
Рабочее окно Camunda Modeler

Пример делегата на Java:

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate; public class JavaExampleDelegate implements JavaDelegate
}

Пример делегата на Kotlin:

import org.camunda.bpm.engine.delegate.DelegateExecution
import org.camunda.bpm.engine.delegate.JavaDelegate class KotlinExampleDelegate: JavaDelegate { override fun execute(execution: DelegateExecution) { val someVar = execution.getVariable("someVariable") //some code execution.setVariable("otherVariable", "someValue") }
}

В делегате можно описывать бизнес-логику, интеграции и всё, что душе угодно.

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

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

Это то, чего мы хотели?

В самом начале, при выборе инструмента, мы искали решение со следующими возможностями:

  • Восстановление процесса ровно с того места, где произошел сбой, и желательно, чтобы это было из коробки.
  • Некоторый GUI, где можно посмотреть, что вообще с процессом происходит.
  • Возможность написания юнит-тестов не только на логику и интеграцию, но и на сам процесс.
  • Java 8 и выше.
  • Развитое сообщество.

С возможностью восстановления и анализа ошибок у Camunda все отлично.

Последнее сделать достаточно легко, просто реализовав DefaultIncidentHandler. Хорошо читаемый трейс, возможность задания числа попыток выполнить шаг перед падением, кастомный обработчик при падении — например, если при падении мы хотим поменять статус некоторой сущности на Error. Не могу сказать, что это — супербаг или проблема. Правда, есть забавный момент при работе этого обработчика: код восстановления из ошибки срабатывает при каждом заходе на шаг процесса. Скорее, об этом нужно просто помнить и учитывать при разработке.

Мы решили это примерно так:

override fun resolveIncident(context: IncidentContext) { val incidentList = Context.getCommandContext().incidentManager.findIncidentByConfiguration(context.configuration) if (incidentList.isNotEmpty()) { // некоторый код при восстановлении инцидента }
}

GUI у Camunda есть, и он неплохой.

В дефолтном UI только минимальный функционал, зато есть очень мощный Rest API, который позволяет создать свою админку — крутую и навороченную. Но если хочется чуть больше, например миграцию инстансов между версиями процессов, то уже придется потрудиться.

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

Например, стартовать процесс можно по /process-definition/key/aProcessDefinitionKey/start таким нехитрым запросом: Rest у Camunda действительно мощный и позволяет творить с процессами практически что угодно.

{ "variables": { "aVariable" : { "value" : "aStringValue", "type": "String" }, "anotherVariable" : { "value" : true, "type": "Boolean" } }, "businessKey" : "myBusinessKey"
}

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

Плюс есть довольно интересная библиотека для тестирования самого процесса — 'org.camunda.bpm.extension', name: 'camunda-bpm-assert'. Для юнит-тестирования мы используем обычный Junit. С ее помощью можно описывать тесты для проверки flow-процесса.

Такое тестирование защищает, например, от неаккуратного рефакторинга и несколько раз действительно нас выручало. Это довольно удобно, так как искать проблемы в случае багов во flow зачастую сложнее, чем в коде.

Kotlin очень хорошо вписался в проект и позволил сосредоточиться только на написании бизнес-логики. Необходимость в Java 8 частично отпала, так как использование Kotlin на многих процессах устранило потребность в «восьмерке». Сущности с большим числом полей, которыми славятся практически все приложения с интеграциями, теперь выглядят не так страшно, и маппинги между сущностями стали гораздо более читабельными. Трудно поверить, но в основном всё то, что говорят о крутости Kotlin, — правда. Часто критикуемое null safety действительно работает и выручает в большинстве случаев.

Об этом говорит тот факт, что постоянно появляются новые библиотеки на GitHub для тестирования и метрик. Community у Camunda достаточно развитое.

Добавить необходимых зависимостей, пару аннотаций и пару конфигурационных бинов — собственно, вот и вся интеграция! Приятно, что Camunda отлично интегрируется со Spring. Взаимодействие происходит через Java API, которое позволяет выполнять манипуляции с процессами из java-кода. В результате мы пишем обычное spring-приложение, к которому все привыкли, добавляя flow бизнес-процесса.

Например, запустить процесс можно всего одной командой:

runtimeService.startProcessInstanceByKey( "MyTestProcess", "MyBusinessKey", mapOf( "key1" to "value1", "key2" to "value2", )
)

Здесь MyTestProcess — Id-шник процесса, а не инстанса. MyBusinessKey — уникальный ключ для запускаемого инстанса процесса. Мы обычно используем для этого поля некое бизнесовое значение — для более быстрой навигации между инстансами и поиском.

Примерно таким же образом можно разбудить «заснувший» процесс.

В итоге за довольно короткий промежуток времени получилось сделать вполне рабочий процесс и благополучно вывести его в продакшен. Заметных минусов или каких-то проблем, с которыми мы столкнулись, особо вспомнить не получается. Сейчас на Camunda у нас запущено около 15 приложений, на которых единовременно крутится около 100 тысяч процессов. На платформе внедряются другие процессы и вполне успешно.

image

Вместо эпилога

Вот несколько ресурсов, которые были полезны при внедрении описанного выше стека. Рекомендую ознакомиться с ними, если интересна дополнительная информация по теме.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть