События сигналов (Signal Events)

Этот раздел перенесён из документации Camunda 7 и в дальнейшем будет доработан с учётом особенностей OpenBPM Engine

События сигналов — это события, которые ссылаются на именованный сигнал. Сигнал является событием с глобальной областью видимости (семантика широковещательной рассылки, broadcast) и доставляется всем активным обработчикам.

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

event signal throwing

Этот сигнал может быть перехвачен всеми экземплярами процессов, которые на него подписаны. Ниже приведён пример процесса, подписывающегося на данный сигнал.

event signal catching

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

Определение события сигнала

Определение события сигнала объявляется с помощью элемента signalEventDefinition. Атрибут signalRef ссылается на элемент signal, объявленный как дочерний элемент корневого элемента definitions. Ниже приведён фрагмент процесса, в котором сигнал выбрасывается и перехватывается промежуточными событиями. Элементы signalEventDefinition ссылаются на «глобальный» элемент сигнала.

<definitions>
  <!-- declaration of the signal -->
  <signal id="alertSignal" name="alert" />

  <process id="catchSignal">
    <intermediateThrowEvent id="throwSignalEvent" name="Alert">
      <!-- signal event definition -->
      <signalEventDefinition signalRef="alertSignal" />
    </intermediateThrowEvent>
    <!-- ... -->
    <intermediateCatchEvent id="catchSignalEvent" name="On Alert">
      <!-- signal event definition -->
      <signalEventDefinition signalRef="alertSignal" />
    </intermediateCatchEvent>
    <!-- ... -->
  </process>
</definitions>

Примечание: в отличие от других событий, например событий ошибки, сигнал не «поглощается» при перехвате. Если существуют два активных граничных события сигнала, перехватывающих один и тот же сигнал, будут активированы оба граничных события, даже если они принадлежат разным экземплярам процессов.

Выражения

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

Используя выражения в имени сигнала, можно динамически изменять имя сигнала на основе процессных переменных. Это может быть полезно, например, при необходимости прерывания параллельных веток выполнения. Пример:

<signal id="alertSignal" name="alert-${execution.processBusinessKey}" />

Signal API

Инициация (выбрасывание) сигналов

Сигнал может быть выброшен либо экземпляром процесса с использованием BPMN-конструкции, либо программно через Java API. Сервис RuntimeService предоставляет fluent API для программного выбрасывания сигналов:

// широковещательная рассылка сигнала
runtimeService
  .createSignalEvent("signalName")
  .setVariables(variables)
  .send();

// доставка сигнала конкретному выполнению
runtimeService
  .createSignalEvent("signalName")
  .executionId(executionId)
  .setVariables(variables)
  .send();

Также можно использовать один из следующих методов RuntimeService:

RuntimeService.signalEventReceived(String signalName);
RuntimeService.signalEventReceived(String signalName, String executionId);

Если указан executionId, сигнал доставляется только конкретному выполнению. В противном случае сигнал рассылается всем подписанным обработчикам (семантика broadcast).

Примечание: событие сигнала не выполняет корреляцию с конкретным экземпляром процесса. Напротив, оно рассылается всем экземплярам процессов. Если требуется доставить сигнал исключительно конкретному экземпляру процесса, не следует использовать BPMN-событие выбрасывания сигнала. Вместо этого необходимо выполнить корреляцию вручную с использованием соответствующих запросов и доставить сигнал конкретному выполнению программно.

Поиск подписок на события сигналов

Можно выполнить запрос всех выполнений, подписанных на определённый сигнал:

List<Execution> executions = runtimeService.createExecutionQuery()
    .signalEventSubscriptionName("alert")
    .list();

После этого можно использовать Signal API для доставки сигнала этим выполнениям.

Перехват событий сигналов

Стартовое событие сигнала (Signal Start Event)

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

При деплое определения процесса с одним или несколькими стартовыми событиями сигнала применяются следующие правила:

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

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

  • Версионирование процессов: при деплое новой версии определения процесса подписки на сигналы предыдущей версии отменяются. Это также относится к событиям сигналов, отсутствующим в новой версии.

Экземпляр процесса, определённого со стартовыми событиями сигнала, будет запущен при выбрасывании сигнала с соответствующим именем. Сигнал может быть выброшен либо другим процессом (через промежуточное или конечное выбрасывающее событие сигнала), либо с помощью следующих методов RuntimeService:

void signalEventReceived(String signalName);
void signalEventReceived(String signalName, Map<String, Object> processVariables);

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

XML-представление стартового события сигнала — это обычное объявление стартового события с дочерним элементом signalEventDefinition:

<startEvent id="signalStart" >
  <signalEventDefinition signalRef="alertSignal" />
</startEvent>

Промежуточное перехватывающее событие сигнала (Signal Intermediate Catching Event)

Когда токен достигает промежуточного перехватывающего события сигнала, он остаётся в ожидании до тех пор, пока не будет получен сигнал с соответствующим именем.

<intermediateCatchEvent id="signal">
  <signalEventDefinition signalRef="newCustomerSignal" />
</intermediateCatchEvent>

Расширения OpenBPM Engine

Для промежуточного перехватывающего события сигнала поддерживаются следующие расширения:

Атрибуты

Элементы расширений

Ограничения

Граничное событие сигнала (Signal Boundary Event)

Когда выполнение достигает активности, к которой прикреплено граничное событие сигнала, это событие начинает перехватывать сигналы с соответствующим именем.

Примечание: в отличие от других событий, таких как граничное событие ошибки, граничное событие сигнала не ограничивается перехватом сигналов, выброшенных в пределах области видимости прикреплённой активности. Событие сигнала имеет глобальную область видимости (broadcast), что означает, что сигнал может быть выброшен из любого места, даже из другого экземпляра процесса.

<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
  <signalEventDefinition signalRef="alertSignal"/>
</boundaryEvent>

Выбрасывание событий сигналов

Промежуточное выбрасывающее событие сигнала (Signal Intermediate Throwing Event)

Промежуточное выбрасывающее событие сигнала выбрасывает сигнал для заданного сигнала.

Сигнал рассылается всем активным обработчикам (т.е. всем перехватывающим событиям сигнала). Сигналы могут публиковаться синхронно или асинхронно.

  • В конфигурации по умолчанию сигнал доставляется синхронно. Это означает, что экземпляр процесса, выбрасывающий сигнал, ожидает, пока сигнал будет доставлен всем перехватывающим экземплярам процессов. Уведомление перехватывающих экземпляров происходит в рамках одной транзакции с выбрасывающим экземпляром, поэтому если один из уведомлённых экземпляров завершится технической ошибкой (выбросит исключение), все участвующие экземпляры завершатся с ошибкой.

  • Сигнал также может быть доставлен асинхронно. В этом случае определяется, какие обработчики активны в момент достижения выбрасывающего события сигнала. Для каждого активного обработчика создаётся асинхронное уведомление (Job), которое затем исполняется JobExecutor.

Промежуточное событие сигнала определяется как промежуточное выбрасывающее событие с элементом signalEventDefinition.

<intermediateThrowEvent id="signal">
  <signalEventDefinition signalRef="newCustomerSignal" />
</intermediateThrowEvent>

Асинхронное выбрасывание сигнала выглядит следующим образом:

<intermediateThrowEvent id="signal">
  <signalEventDefinition signalRef="newCustomerSignal" camunda:asyncBefore="true" />
</intermediateThrowEvent>

Конечное событие сигнала (Signal End Event)

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

<endEvent id="signal">
        <signalEventDefinition signalRef="newCustomerSignal" />
</endEvent>

Передача переменных

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

<signalEventDefinition signalRef="newCustomerSignal">
    <extensionElements>
        <camunda:in source="throwingVariableName" target="catchingVariableName" />
    </extensionElements>
</signalEventDefinition>

Переменные, объявленные в элементах camunda:in, устанавливаются в максимально возможной области видимости в перехватывающем экземпляре процесса.

Также можно использовать выражения и модифицировать данные перед их передачей в перехватывающие процессы.

<signalEventDefinition signalRef="newCustomerSignal">
    <extensionElements>
        <camunda:in sourceExpression="${X + 5}" target="Y" />
    </extensionElements>
</signalEventDefinition>

Переменная процесса Y в перехватывающих экземплярах будет иметь значение (X + 5), где X — процессная переменная экземпляра, выбрасывающего сигнал.

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

<signalEventDefinition signalRef="newCustomerSignal">
    <extensionElements>
        <camunda:in variables="all" />
    </extensionElements>
</signalEventDefinition>

При установке local="true" будут переданы только локальные переменные выполнения, которое исполняет выбрасывающее событие сигнала. Это те переменные, которые могут быть объявлены как входные параметры.

<signalEventDefinition signalRef="newCustomerSignal">
    <extensionElements>
        <camunda:in variables="all" local="true" />
    </extensionElements>
</signalEventDefinition>

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

<signalEventDefinition signalRef="newCustomerSignal">
    <extensionElements>
        <camunda:in variables="all" local="true" />
        <camunda:in source="X" target="Y" />
        <camunda:in sourceExpression="${X + 5}" target="Z" />
    </extensionElements>
</signalEventDefinition>

Передача Business Key

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

<signalEventDefinition signalRef="newCustomerSignal">
    <extensionElements>
          <camunda:in businessKey="${execution.processBusinessKey}" />
    </extensionElements>
</signalEventDefinition>

Элемент camunda:in для Business Key может использоваться совместно с элементами camunda:in для передачи процессных переменных.

Расширения OpenBPM Engine

Для промежуточных и конечных выбрасывающих событий сигнала поддерживаются следующие расширения:

Атрибуты

Элементы расширений

Ограничения

Дополнительные материалы

Лицензия и атрибуция

Эта документация была создана на базе материала "Camunda 7 Docs" от Camunda, находится под лицензией Creative Commons Attribution-ShareAlike 3.0 Unported License .

Оригинал документации: https://docs.camunda.org