Первый проект на Camunda: добавляем формы и автоматизацию

В прошлой статье остановились на том,  что научились делать простые формы для ввода данных в бизнес-процессы через Camunda Modeler. Формочки были примитивные, данные были размазаны по XML-файлу и вообще было плохо. Исправляем в этой статье!

Видеоверсия

Выделяем явную структуру объекта заявки

Для отображения каких-то данных на форме мы использовали простые типы данных — строки, булевы переменные, дробные числа и так далее. Из этого формировалась форма для ввода этих данных.

Форма для ввода данных в Camunda

С таким подходом есть несколько существенных проблем:

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

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

Избавиться от этого можно, явно описав нашу сущность заявки. Сущность назовём BusinessTrip, а хранить её будем в контексте под названием application.

Чтобы это сделать, создадим в нашем приложении класс BusinessTrip.kt:

Data класс на Kotlin для Camunda

Класс довольно наивный, в следующих статьях будем это исправлять, а пока это нам не помешает учиться.  Надо обратить внимание на приставку data перед словом class  — компилятор Kotlin сделает некоторые полезные вещи за нас, если мы будем указывать это слово.

Настраиваем сереализацию для Camunda в Kotlin

Так же Kotlin потребует дополнительной настройки, потому что Kotlin не требуются getter\setter, как в Java.  Настройка нужна будет, потому что Camunda написана на java и использует библиотеку Jackson, которая опирается на эти геттеры и сеттеры, а их нет.

  • Включим зависимость Jackson-kotlin, которая будет автоматически под капотом обрабатывать Kotlin классы, как будто там есть геттеры и сеттеры:

Добавляем jackson-kotlin

  • Переопределим функции получения формата данных. Просто скопируйте код из гита.

Конфигурируем Jackson для Camunda на Kotlin

  • Последнее — создайте папку services в папке META-INF, создайте там файл с указанным именем и впишите туда название класса из пред.пункта.

Настраиваем SPIN для Camunda

Заменяем формы на Angular

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

  • Создадим первую, стартовую форму. Создайте пустой файл:

Место файлика с формой в структуре проекта

  • Откройте свою BPMN-схему и замените атрибуты формы:

Таким образом указывается ссылка на форму Camunda

  • Нам нужно написать код самой формы. Допустим, мы хотим получить такой результат:

Требуемый результат формы

Фишки, которые невозможны в формах в Camunda Modeler — это обязательность заполнения полей, автоподстановка текущего логина в поле Employee.

  • Давайте посмотрим на содержимое файла startForm.html

 Встроенная библиотека от Camunda требует, чтобы вся форма была завернута в html-тег <form>.

  • 1 кусок кода получает текущий UserName пользователя и сохраняет его в объект $scope.
  • 2 кусок кода используется для того, чтобы вываливать календари в полях с датой.
  • 3 кусок кода после загрузки формы создает переменную нужного типа BusinessTrip, которая в объекте $scope называется dataObject. Через этот объект мы будем взаимодействовать непосредственно с HTML-элементами формы за счёт магии ангуляра.

Развернём div:

Содержимое формы на Angular в Camunda

В целом это обычный HTML и Angular 1- надо обратить внимание на директивы ng-model — за счёт этого мы ссылаемся на конкретный атрибут сущности. А с помощью директив cam-variable-name и cam-variable-type указываем типы данных, которые понимает Camunda. Angular позволяет осуществить связывание данных из HTML input с объектом dataObject и его атрибутами, которые после выполнения формы будут отправлены на сервер.

Эта форма стартовая, поэтому мы создаём переменную. В других формах нам переменную нужно получить, потому что она уже лежит в контексте:

Код доставания переменной из контекста для отображения на форме Camunda

Таким образом мы создаем формы для каждой из задач.

Добавим автоматческую отправку e-mail нотификации

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

Квадратик, который будет автоматизирован

Откройте вашу XML и впишите в квадратик такую информацию:

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

  • 1 Квадратик — Есть несколько способов указать, какой именно код вызывать — пока воспользуемся Delegate Expression.
  • 2 Квадратик — Camunda будет пытаться выполнить наш код сразу же при получении команды на исполнение, синхронно. Если е-мейл сервер не ответит, то процесс даже не встанет на этот квадратик. Такие отметки, как в квадратике 2, решат этот вопрос. Подробнее про них поговорим в других уроках.

Посмотрим на класс, который будет реализовывать отправку е-мейла:

Над классом стоит текст @Component — это аннотация, которая позволит Camunda найти  этот кусок кода. Во втором квадратике стоят поля с аннотацией @Value — она позволяет взять настройки из файла application.properties, который лежит в папке resources. Вот так, например, раздел с этими настройками в файле выглядит у меня:

Настройки для отправки писем

А для отправки непосредственно почты будем использовать библиотеку Simple Java Mail.  Включите её в pom.xml по инструкции с сайта.

Для того, чтобы Camunda смогла вызвать наш класс, он должен наследоваться от класса JavaDelegate и реализовывать абстрактный метод execute:

Код, который будет работать с Camunda

В метод execute приходит объект execution, который даёт нам доступ ко всем внутренностям системы и конкретного инстанса, в котором вызывается наш квадратик. Например, вот так я получаю заявку из контекста:

Fall application = execution. getVariable ("application") as Business Trip

А вот так я пытаюсь получить из Camunda email пользователя, который был указан в поле employee заявки:

val emailTo = execution.processEngineServices.identityService.createUserQuery().userId(application.employee)?.singleResult()?.email

Ну а дальше, просто отправляю e-mail с настройками из application.properties и данными из объекта application типа BusinessTrip по инструкции от библиотеки:

val subject = "Your trip from ${application.from} to ${application.to} is ready!"
var body = "Here you trip details \n" +
        "------ \n" +
        "From: ${application.from} \n" +
        "To:  ${application.to} \n" +
        "Fly description:  ${application.flyDescription} \n" +
        "Hotel description:  ${application.hotelDescription} \n" +
        "------ \n" +
        "Bye!"

if (emailTo != null) {
    val email = EmailBuilder.startingBlank()
            .from(smtpFromName, smtpFromEmail!!)
            .to(emailTo)
            .withSubject(subject)
            .withPlainText(body)
            .buildEmail()


    val mailer = MailerBuilder
            .withSMTPServer(smtpHost, smtpPort, smtpUserName, smtpPassword)
            .withTransportStrategy(TransportStrategy.SMTPS)
            .clearEmailAddressCriteria() // turns off email validation
            .buildMailer()

    mailer.sendMail(email)
}

В итоге

Наше решение стало лучше, теперь мы:

  • Имеем явновыраженную сущность, с которой хотим работать.
  • Интерактивные( +-) формы, которые умеют делать автоподстановки
  • Заменили ручную задачу на автоматическую, сэкономили ресурсы людей.

Но мы по прежнему далеки от идеала:

  • Формы надо копипастить для каждой задачи отдельно.
  • Стили на формах не очень красивые.
  • Старый этот Angular уже не поддерживают.
  • Храним данные в базе Camunda, что плохо (узнаете почему в след. уроке).

Мои исходники доступны тут:. https://github.com/KotskinKotskin/camunda-first-bpmn-process

 

Всё получилось? Завелось?  Пишите в комментарии и поделитесь статьей.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Комментарии

Вам так же понравится

Сообщить об опечатке

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