Условные события (Conditional Events)

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

Условное событие (Conditional Event) определяет событие, которое срабатывает, если заданное условие вычисляется в значение true. Оно может использоваться как стартовое событие событийного подпроцесса (Event Sub-Process), как промежуточное событие и как граничное событие. Стартовое и граничное событие могут быть прерывающими и непрерывающими.

В OpenBPM условные события срабатывают с помощью переменных процесса. Подробности см. в разделе Срабатывание условных событий Срабатывание условных событий (Trigger Conditional Events).

В следующей BPMN-модели используются все поддерживаемые условные события.

Обзор условных событий

Как видно, промежуточное условное событие действует как ожидание до момента выполнения условия. В этом примере, если процессор становится доступным и условие имеет, например, вид ${processorAvailable == true}, то условие будет выполнено и выполнение процесса продолжится к следующей активности.

Если выполняется условие граничного условного события, проверяющего, была ли изменена заявка, то соответствующая User Task будет прервана.

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

Условие (Condition)

Чтобы задать, когда должно срабатывать условное событие, необходимо указать элемент condition в качестве вложенного элемента conditionalEventDefinition.

<conditionalEventDefinition>
  <condition type="tFormalExpression">${var1 == 1}</condition>
</conditionalEventDefinition>

Заданное условие может быть выражением EL и имеет доступ к переменным экземпляра процесса. Подробнее о выражениях EL см. в разделе Expression Language. Условие вычисляется каждый раз при изменении переменной, подробности см. в разделе Срабатывание условных событий Срабатывание условных событий (Trigger Conditional Events).

Чтобы предотвратить постоянное вычисление условия, его вычисление может быть ограничено определёнными изменениями переменных. Для этого можно использовать атрибуты расширения OpenBPM camunda:variableName и camunda:variableEvents.

По умолчанию вычисление условия инициируется любым изменением переменной, то есть созданием/обновлением/удалением любой переменной. С помощью variableName его можно ограничить изменениями конкретной переменной. С помощью variableEvents можно ограничить тип изменения. Можно указать несколько событий изменения переменной в виде списка, разделённого запятыми. Эти атрибуты можно использовать в сочетании.

Элемент conditionalEventDefinition может, например, выглядеть так:

<conditionalEventDefinition camunda:variableName="var1"
                            camunda:variableEvents="create, update">
  <condition type="tFormalExpression">${var1 == 1}</condition>
</conditionalEventDefinition>

Приведённое выше условие вычисляется только в том случае, если переменная var1 создаётся или обновляется. Эти атрибуты особенно полезны для непрерывающих событий, поскольку такие события могут срабатывать более одного раза!

Граничное условное событие (Conditional Boundary Event)

Граничное условное событие действует как наблюдатель, который срабатывает при выполнении определённого условия.

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

В XML-представлении непрерывающих условных событий атрибут cancelActivity устанавливается в значение false:

<boundaryEvent id="conditionalEvent" attachedToRef="taskWithCondition" cancelActivity="false">
  <conditionalEventDefinition>
    <condition type="tFormalExpression">${var1 == 1}</condition>
  </conditionalEventDefinition>
</boundaryEvent>

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

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

Промежуточное условное событие определяется как промежуточное перехватывающее событие (Intermediate Catch Event). Конкретным типом вложенного элемента в данном случае является элемент conditionalEventDefinition.

<intermediateCatchEvent id="conditionalEvent">
  <conditionalEventDefinition>
    <condition type="tFormalExpression">${var1 == 1}</condition>
  </conditionalEventDefinition>
</intermediateCatchEvent>

Условное стартовое событие (Conditional Start Event)

Условное стартовое событие может использоваться для запуска процесса путём вычисления некоторого условия. Один процесс может иметь одно или несколько условных стартовых событий.

Если выполняется более одного условия, будет инициировано соответствующее число процессов.

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

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

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

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

List<ProcessInstance> instances = runtimeService
    .createConditionEvaluation()
    .setVariable("temperature", 24)
    .evaluateStartConditions();
// or
List<ProcessInstance> instances = runtimeService
    .createConditionEvaluation()
    .setVariables(variableMap)
    .evaluateStartConditions();

Переданные переменные используются для вычисления условий. Кроме того, они передаются как переменные во вновь создаваемые экземпляры процессов. XML-представление условного стартового события — это обычное объявление стартового события с дочерним элементом conditionalEventDefinition.

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

<startEvent id="conditionalStartEvent">
  <conditionalEventDefinition camunda:variableName="temperature">
    <condition type="tFormalExpression">${temperature > 20}</condition>
  </conditionalEventDefinition>
</startEvent>

Условное стартовое событие для событийного подпроцесса (Conditional Start Event for Event Sub-Process)

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

Примечание: Event Sub-Process должен иметь единственное стартовое событие.

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

<subProcess id="EventSubProcess" triggeredByEvent="true">
  <startEvent id="conditionalStartEvent">
    <conditionalEventDefinition>
      <condition type="tFormalExpression">${var1 == 1}</condition>
    </conditionalEventDefinition>
  </startEvent>
</subProcess>

Срабатывание условных событий (Trigger Conditional Events)

Срабатывание при инстанцировании области видимости

Когда инстанцируется BPMN-область видимости, вычисляются условия событий, доступные в этой области видимости. Это поведение называется срабатыванием при инстанцировании области видимости.

Рассмотрим следующую модель процесса:

event conditional2

При запуске экземпляра процесса, то есть при инстанцировании области видимости определения процесса, условие подпроцесса вычисляется до выполнения пустого стартового события (none start event). Если оно выполнено, событие срабатывает немедленно, и пустое стартовое событие никогда не выполняется. То же относится к активностям с граничными условными событиями и промежуточными условными событиями.

Срабатывание через Variable API

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

Установка переменной извне

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

  //set variable on process instance
  runtimeService.setVariable(processInstance.getId(), "variable", 1);

Этот вызов инициирует вычисление всех применимых условных событий. Подробности см. в разделах Вычисление сверху вниз Вычисление сверху вниз (Top-Down Evaluation) и Вычисление с учётом области видимости Вычисление с учётом области видимости (Scoped Evaluation).

Установка переменной из делегатного кода

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

Например:

public class SetVariableDelegate implements JavaDelegate {
  @Override
  public void execute(DelegateExecution execution) throws Exception {
    execution.setVariable("variable", 1);
  }
}

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

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

API Services

  • Starting соответствует начальной фазе экземпляра активности. В это время вызываются входные мэппинги и start-листенеры исполнения.

  • Execute соответствует фазе выполнения экземпляра активности.

  • Ending соответствует завершающей фазе экземпляра активности. В это время вызываются выходные мэппинги и end-листенеры исполнения.

Например, предположим, что переменная устанавливается в start-листенере исполнения активности. Условные события срабатывают только после того, как все start-листенеры были выполнены и экземпляр активности готов перейти в фазу Execute.

Вычисление сверху вниз (Top-Down Evaluation)

Изменение переменной вызывает вычисление условия и срабатывание события по принципу сверху вниз. Это означает, что вычисление начинается с условных событий BPMN-области видимости, в которой была изменена переменная. Затем оно шаг за шагом спускается в экземпляры вложенных BPMN-областей видимости (например, встроенных подпроцессов). Это продолжается до тех пор, пока не сработает условное событие, прерывающее текущий экземпляр области видимости (тем самым отменяя все дочерние), либо пока не закончатся более глубоко вложенные области видимости.

Например, рассмотрим следующую BPMN-модель процесса:

conditionalEventScopesHighestFirst

Если переменная устанавливается в контексте экземпляра подпроцесса, то сначала вычисляется граничное условное событие подпроцесса. Если условие выполнено, исполнение прерывается, в противном случае вычисляется граничное условное событие UserTask B и срабатывает, если условие выполнено.

Вычисление с учётом области видимости (Scoped Evaluation)

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

Рассмотрим следующую BPMN-модель процесса:

conditionalEventScopes

Если мы запустили приведённый выше процесс и активны UserTask B и UserTask A, то иерархия экземпляров активности выглядит так:

ProcessInstance
   UserTask A
   SubProcess
     UserTask B

Если переменная устанавливается в контексте экземпляра SubProcess, то вычисляется только граничное условное событие UserTask B. Граничное событие UserTask A не может сработать, так как переменная не видима в его контексте. Раздел руководства пользователя об областях видимости и видимости переменных содержит подробное описание общей концепции.

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

Атрибуты

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

Ограничения

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

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

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

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