Events
Overview
In the BPMN notation, events represent occurrences that happen during a business process. They are capable of initiating the start, continuation, or completion of activities within the process.
Events can be utilized to model various scenarios, such as the receipt of a message, the passage of time, or the occurrence of an error. By incorporating events into BPMN diagrams, users can effectively capture the behavior and flow of a business process.
The word 'event' is used in two different senses:
Events can occur without being represented on the process diagram. For example, message events should be thrown programmatically. |
Events Classification
First, events differ by a position they hold in the process, it may be the beginning, middle, or end. So we talk about start, intermediate, or end events.
The behavior of the event is defined by trigger activating it. For example, message or timer.
The process can consume or produce events. So, BPMN events in these roles are called 'catching' and 'throwing' events.
As well, some events can be attached to activities; such events are called 'boundary'.
Besides, the event may have a property to interrupt the process or let it go on. In this case, we talk about interruptible and non-interruptible events.
For your convenience, events classification is summarized in a table below:
Criteria | Options |
---|---|
Position in the process |
Start, Intermediate, End, |
Trigger |
None, Timer, Message, Signal, Error, Compensation |
Role |
Catching/Throwing |
Is attached to activity? |
Boundary |
Can interrupt the process? |
Interrupting or Non-interrupting |
Position in the Process
Depending on its position in the process, events can be:
All events are visualized as a circle, where the style of a line (thin, double, or thick) says about a position of event in the process (start, intermediate, or end).
You can see an example of events representation in the XML below:
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:startEvent id="start-event" name="Start event"> (1)
<bpmn:outgoing>Flow_out_start</bpmn:outgoing>
</bpmn:startEvent>
. . .
<bpmn:intermediateThrowEvent id="intermediate-event" name="Intermediate event"> (2)
<bpmn:incoming>Flow_in</bpmn:incoming>
<bpmn:outgoing>Flow_out</bpmn:outgoing>
</bpmn:intermediateThrowEvent>
. . .
<bpmn:endEvent id="end-event" name="End event"> (3)
<bpmn:incoming>Flow_in_end</bpmn:incoming>
</bpmn:endEvent>
</bpmn:process>
1 | — Start event |
2 | — Intermediate event |
3 | — End event |
Event Triggers
Event triggers in BPMN are used to indicate when a specific event should occur within a business process. There are several types of event triggers commonly used in BPMN, including the following:
-
None (events without trigger)
Triggers can be activated manually or via API call.
Catching and Throwing Events
In BPMN 2.0, there exist two main event categories: catching and throwing events.
-
Catching: when process execution arrives at the event, it will wait for a trigger to happen. The type of trigger is defined by the inner icon or the type declaration in the XML. Catching events are visually differentiated from a throwing event by the inner icon that is not filled (usually white).
-
Throwing: when process execution arrives at the event, a trigger is fired. The type of trigger is defined by the inner icon or the type declaration in the XML. Throwing events are visually differentiated from a catching event by the inner icon that is filled (usually black).
For example, see below catching and throwing signal events:
Boundary Events
Boundary events are catching events that are attached to an activity (task, embedded subprocess or call activity). It can be more than one event attached to the activity. Boundary events are always catching.
Event subprocess can’t have boundary events. |
In the XML, a boundary event is marked by special tag and has an attribute attachedToRef
that refers to the activity it is attached to:
<boundaryEvent id="Event_0gl2f4v" attachedToRef="Activity_1fsayqc">
<timerEventDefinition id="TimerEventDefinition_0w9bip4" />
</boundaryEvent>
Example
Boundary events can be attached to task, call activity or embedded subprocess.
While the activity is running, the event is listening for a designated type of trigger. When the trigger fired, the activity the event is attached to can be interrupted or not, depends on the type of event, interrupting or non-interrupting.
Process Interruption
The event can interrupt normal process execution. This is applicable to boundary events and start events in event subprocesses.
-
Interrupting — the activity is interrupted, and the sequence flow going out of the event is followed.
-
Non-interrupting — a new execution runs in parallel with the main activity and does not disrupt its flow.
Interrupting event is visualized as a regular intermediate event, attached to the activity (task or subprocess), whereas a non-interrupting event has a dash-line border.
Non-interrupting event can trigger multiple times, and each time a new execution will start (a new token generated) until the task to be completed. For example, non-interrupting cyclic timer will fire every 5 minutes and send a notification to the user.
Type of behavior is defined by cancelActivity
attribute.
By default, it is set to true
and the attribute usually omitted for interrupting events.
For non-interrupting events its value is explicitly set to false
.
For example, see non-interrupting timer event:
<boundaryEvent id="Event_01" cancelActivity="false" (1)
attachedToRef="user-task">
<timerEventDefinition id="TimerEventDefinition_14a8e0l" />
</boundaryEvent>
1 | — Defines non-interrupting event. |
Event Definitions
In BPMN, the messages and signals are a mechanism used to communicate between different elements within a business process or between processes. Both messages and signals play a crucial role in defining the interactions and dependencies between various elements in a BPMN diagram. Errors are similar to messages and signals, as they allow for the control of the process flow.
Messages and signals must be defined before they can be used in events. Error definitions in some cases can be omitted.
To define an event in Studio, open a process model, select nothing to access the process properties and find signal and message definition sections:
In the case of collaboration, select the desired participant (pool). |
To create a message definition, set its id and name:
To create a signal definition, set its id and name; besides, you must select a scope parameter, Global or Process instance:
To create an error definition, set its id and name; besides, you may set Error code:
Message, signal, and error definitions in the XML file are located usually between <process> and <diagram> sections.
</process>
<message id="green" name="Green" /> (1)
<message id="yellow" name="Yellow" />
<message id="red" name="Red" />
<signal id="ready" name="Ready" flowable:scope="global" /> (2)
<signal id="stop" name="Stop" flowable:scope="processInstance" />
<error id="failure" name="Failure" errorCode="500" /> (3)
<error id="fatal" name="Fatal" /> <bpmndi:BPMNDiagram id="BPMNDiagram_process">
1 | — Message definitions |
2 | — Signal definitions |
3 | — Error definitions |
If you plan to use the same messages and signals across various processes, you must create their definitions in each BPMN model. |
Event subprocesses can have interrupting or non-interrupting start events.
-
Interrupting — when event subprocess ends, the main process to be terminated.
-
Non-interrupting — event subprocess executes in parallel and comes to its end, the main process continues.
In the picture above, the first subprocess interrupts the main process when time is over. The second subprocess executes a service task and ends not affecting the main process.
Event Subscriptions
An event subscription is a mechanism that allows a process to wait for a specific event to occur before continuing its execution. Event subscription types are:
-
Message
-
Signal
-
Timer
-
Error
-
Compensation
There are two cases:
-
Start events — Subscriptions are created at deployment time.
-
Intermediate and boundary events — Subscriptions are created when execution reaches the event.
Each event subscription can be configured with parameters that define how the event should be correlated with the process instance. This includes specifying event types, names, and any required correlation parameters that must match for the subscription to be triggered.
The event subscriptions are stored in the database, in the ACT_RU_EVENT_SUBSCR
table.
This table holds information about the event type, process instance ID, and any correlation parameters needed for message events.
When the corresponding event occurs, (e.g., a message is received, or a timer expires), process engine checks the event subscriptions to find any that match the event criteria. For message events, the application must correlate the incoming message to the correct process instance using correlation parameters.
-
Creating Event Subscriptions
You can create event subscriptions for message, signal, and timer events programmatically. For example, you can start a process instance by sending a message:
// Start a process instance with a message ProcessInstance processInstance = runtimeService.startProcessInstanceByMessage("orderPlaced", processVariables);
-
Querying Event Subscriptions
You can query for existing event subscriptions to see which processes are waiting for specific events. For example:
List<EventSubscription> messageSubscriptions = runtimeService.createEventSubscriptionQuery() .eventType("message") .list();
-
Getting Event Subscriptions
You can get a list of subscriptions using
RuntimeService
API. For example, signal subscriptions:// Query for all signal event subscriptions List<EventSubscription> signalSubscriptions = runtimeService.createEventSubscriptionQuery() .eventType("signal") .list();
For other types of events, use
"message"
,"error"
, and"compensate"
respectively.For timers, use
ManagementService
:List<Job> timerJobs = managementService.createTimerJobQuery().list();
-
Triggering Event Subscriptions
You can trigger event subscriptions programmatically when the corresponding event occurs. For example, to trigger a message event:
runtimeService.messageEventReceived("orderPlaced", executionId, processVariables);
-
Deleting Event Subscriptions
You can delete event subscriptions if they are no longer necessary. For example, to delete a specific event subscription:
runtimeService.createEventSubscriptionQuery() .eventType("message") .processInstanceId(processInstanceId) .singleResult();
See the Listeners section.
Start Events
A start event is the entry point of the process. When the engine tries to begin execution of the process, it searches for the start event in the BPMN model.
So, the process MUST have a Start event. Start events are always catching: conceptually, the event is (at any time) waiting until a certain trigger happens.
Start events can be of the following types:
-
Error start event (In event subprocesses only)
Although BPMN allows multiple start events, the process technically may have only one none start event. Otherwise, it will cause error at deployment. Don’t use more than one none start event like in the picture below:
However, it is possible to use multiple start events of other types:
You can use several message (or signal) start events provided the messages (or signals) differ.
Intermediate Events
Events placed between the beginning and the end of the process are intermediate.
End Events
An end event signifies the end of a path in a process or subprocess. An end event is always throwing. There could be the following end events in Jmix BPM:
Formally, end event isn’t mandatory. The process ends when there are no activities to execute. But it is a good practice to finish each path of the process by the end event.
Don’t try to bring all flows to the single end event – it only makes your diagram messy.
Multiple end events allow to analyze how processes ended.
None Events
None events are unspecified events, also called "blank" events.
None Start Event
A none start event technically means that the trigger for starting the process instance is unspecified. This means that the engine cannot guess when the process instance must be started.
Embedded subprocess always has a none start event. |
A none start event is visualized as a circle with no inner icon (in other words, no trigger type).
None start event has two specific properties:
-
Process variables — provide information about parameters that are used for starting the process via API.
-
Form — defines a user interface when the process is to be started manually.
You can define process variables in the start event by clicking a create link in the BPMN Inspector panel:
Then type a variable name and press 'Enter':
By default, a new variable is created with a String
type, but you can change its type to the desired one.
Process variables defined here wouldn’t be created in the process instance. They must be initialized some way. For example, with script task. |
If process variables are created before the form, they will be added to form automatically.
About the Form settings see the details in the Process Forms section.
The XML representation of a none start event is the normal start event declaration without any sub-element (other start event types all have a sub-element declaring the type).
<startEvent id="startEvent1" name="Start"> (1)
<extensionElements>
<jmix:processVariables>
<jmix:processVariable name="invoiceId" type="string" /> (2)
</jmix:processVariables>
<jmix:formData type="no-form" /> (3)
</extensionElements>
<outgoing>Flow_0h77bcd</outgoing>
</startEvent>
1 | — Start event definition. |
2 | — Process variable. |
3 | — Here may be a form definition. |
Triggering None Start Event via API
The none start event is used when the process instance is started through the API by calling one of the startProcessInstanceByXXX
methods.
For example,
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("process-id");
Flowable API uses the term 'process definition key' that is equivalent to 'process id' in Jmix Studio. |
See details in the Flowable API section.
Intermediate None Event
Intermediate none events can be used to indicate some state achieved in the process. The engine itself doesn’t do anything in the event, it just passes through it.
An intermediate none event is visualized as a circle with a double outline and no inner icon (in other words, no trigger type).
Intermediate none event has no specific properties.
The XML representation of an intermediate none event is the event declaration by intermediateThrowEvent
without any sub-element.
<intermediateThrowEvent id="IntermediateEvent" />
None End Event
A none end event is a type of end event that signifies the completion of a process without any specific outcome or result. It does not trigger any subsequent activities or flows in the process.
None end event is visualized as a circle with a thick outline and no inner icon.
None end event has no specific properties.
<endEvent id="end-event" name="End">
<incoming>Flow_0qwib28</incoming>
</endEvent>
Timer Events
Timer events in BPMN are events that are triggered based on a predefined time or duration. Timer events can be used to control the flow of a process by specifying when certain activities should be executed.
There are two types of timer events:
As well, timers can be used as boundary events, interrupting or non-interrupting.
Timer Start Event
Timer start event is used to create process instances at a given time. It can be used for processes that should start only once or in specific time intervals.
Embedded subprocess cannot have a timer start event, but event subprocess can. |
A timer start event is visualized as a circle with clock inner icon.
Timer start event has a specific property Timer Definition that defines its type and expression. See timer types for details.
XML Representation
The XML representation of a timer start event is the normal start event declaration, with the timer definition sub-element. Please refer to timer definitions for configuration details.
<startEvent id="theStart">
<timerEventDefinition> (1)
. . . (2)
</timerEventDefinition>
</startEvent>
1 | — Timer event definition. |
2 | — Definition child element. |
Using Timer Start Event
In this example, the main process starts by timer event. And it has two event subprocesses also starting by timers. The first one is non-interruptible, it can do some activities at a certain moment from the process start. The second event subprocess has an interruptible timer, that means the main process will be stopped when this timer event fires.
Don’t use initiator variable in a process with timer start event, it causes execution error.
Unless you define and set its value programmatically.
|
Timer Intermediate Event
Timer intermediate event acts as a stopwatch. When an execution arrives at event, a timer is started. When the timer fires after a specified interval or a date coming, the process continues.
Timer intermediate event is a waiting state.
A timer intermediate event is visualized as an intermediate catching event, with the timer icon on the inside.
A timer intermediate event has the same properties as timer start event.
A timer intermediate event is defined as an intermediate catching event.
The specific type sub-element is, in this case, a timerEventDefinition
element.
<intermediateCatchEvent id="timer">
<timerEventDefinition>
<timeDuration>PT8H</timeDuration> (1)
</timerEventDefinition>
</intermediateCatchEvent>
1 | — Timer type, for example, duration . |
Timer Types
The system allows selecting one of three types of timer:
Duration |
— fires after the specified time period. |
Cycle |
— event repeats a certain number of times or according to Cron expression. |
Date |
— fires at specified date; ignored if date is in the past. |
For start timer event duration counts from the moment the process was deployed to server. |
Setting Time
There are two ways of setting time parameter in timers:
-
String in ISO 8601 format
Standard ISO 8601
ISO 8601 is an international standard covering the worldwide exchange and communication of date and time-related data.
2035-06-17T07:42:14 |
— a date of year 2035, 17 of June, time 7 hours 42 minutes 14 seconds |
2050:01:01 |
— a date of year 2050, 1 of January, 00 hours 00 minutes |
PT30D |
— duration of thirty days |
PT10M |
— duration of ten minutes |
P3Y6M4DT12H30M5S |
— duration of three years, six months, four days, twelve hours, thirty minutes, and five seconds |
R3PT10H |
— cyclic period recurring three times every ten hours |
Don’t use very short periods of time, smaller than 3 seconds. BPM isn’t a real-time system. |
See ISO 8601 standard site for the details.
Cron Expressions
Cron is a time-based job scheduling system used in Unix-like operating systems. It allows users to schedule tasks or commands to run at specific times, dates, or intervals. The term "cron" comes from the word "chronos," which means time in Greek.
You can specify time cycle using cron expressions; the example below shows trigger firing every 5 minutes, starting at full hour:
0 0/5 * * * ?
In Timer intermediate event Cron expressions can be used ONLY with a Cyclic timer type. Otherwise, it’d be an error when you try to deploy the process. |
Message Events
Message events are events that reference a Defining a Message. They are used to model communication between different parts of a business process or between different processes. Message events represent the sending (throwing) or receiving (catching) of messages within a process flow.
There are two types of message events:
As well, message events can be used as boundary events.
Message throwing events (intermediate, end) are not supported in Jmix BPM. See workaround. |
Message Start Event
A message start event can be used to start a process instance using a named message.
A message start event is visualized as a circle with a message event symbol. The symbol is unfilled, to represent the catching (receiving) behavior.
Message start event must have filled a Message property referring to the existing message definition. This is mandatory, otherwise it will cause an error at deployment.
The XML representation of a message start event is the normal start event declaration with a messageEventDefinition
child-element:
<startEvent id="Message_start_event>
<messageEventDefinition id="MessageEventDefinition_invoice"
messageRef="new-invoice-message" /> (1)
</startEvent>
1 | — reference to the message definition. |
Using Message Start Event
A process can have one or more message start events, but messages must be different.
When a process is deployed, the engine creates a message subscription for each message start event. Any subscriptions from the previous version of the process will be closed.
The name of the message start event must be unique across all deployed process definitions. If a process definition containing one or more message start events references a message with the same name as a message start event already deployed by a different process definition, process engine will throw an exception upon deployment. |
Triggering Message Start Event Programmatically
When starting a process instance, a message start event can be triggered using startProcessInstanceByMessage
methods on the RuntimeService.
In API call use exactly message name, not id. For example, we have such message definition:
<message id="green" name="Green" />
Then, invoke API method the following way:
runtimeService.startProcessInstanceByMessage("Green");
Message start events are not supported on embedded subprocesses. |
Message Intermediate Catching Event
An intermediate catching message event catches messages with a specified name.
An intermediate catching message event is visualized as a typical intermediate event (circle with double outline), with the message icon inside. The message icon is unfilled to indicate its catch semantics.
An intermediate catching message event has the same properties as a message start event.
A message intermediate event is defined as an intermediate catching event.
The specific type sub-element is a messageEventDefinition
element.
<intermediateCatchEvent id="catch-message-event"
name="Catch message">
<messageEventDefinition id="MessageEventDefinition_16bx9rl"
messageRef="message-one" />
</intermediateCatchEvent>
When an intermediate message catch event is entered, a corresponding message subscription is created. The process instance stops at this point and waits until the message is received. After that, the catch event is completed and the execution continues.
Message intermediate catching event is a waiting state.
In this example, the process will wait for a message after the completion of Activity 1
, and Activity 2
will be executed once the message is received.
Boundary Message Events
An attached intermediate catching message on the boundary of an activity, or boundary message event for short, catches messages with the same message name as the referenced message definition.
Boundary message events can be interruptible (with solid double outline) or non-interruptible (with dashed double outline).
Boundary message events have the same properties as a message start event.
Boundary events are defined as child elements of the activity they attached to. Message events must have messageRef
attribute referring to existing message definition.
Non-interruptible message event has an attribute cancelActivity
=false
.
<task id="Activity_task" name="Task" /> (1)
<boundaryEvent id="interruptible-message-event" name="Message 1" (2)
attachedToRef="Activity_task">
<messageEventDefinition id="MessageEventDefinition_1"
messageRef="messageOne" />
</boundaryEvent>
<boundaryEvent id="non-interruptible-message-event" name="Message 2" (3)
cancelActivity="false" (4)
attachedToRef="Activity_task">
<messageEventDefinition id="MessageEventDefinition_2" messageRef="messageTwo" />
</boundaryEvent>
1 | — A task boundary message events attached to. |
2 | — Interruptible message event. |
3 | — Non-interruptible message event. |
4 | — cancelActivity attribute. |
Signal Events
Signal events are events that reference a signal definition. Broadcasting a signal will trigger all signal events matching the name of the broadcast signal. Signals have a scope, it can be Global or Process instance.
There are the following signal events in Jmix BPM:
Signal end event isn’t supported. Use workaround. |
Signal Start Event
A signal start event can be used to start a process instance using a named signal definition. The process can have one or more signal start events, but signal definitions must differ.
A signal start event is visualized as a circle with a signal event symbol. The symbol is unfilled, to represent the catching (receiving) behavior.
A signal start event has a specific property Signal
that refers to the certain signal definition.
It must be filled and refer to existing signal definition, otherwise it causes error during deployment.
The XML representation of a signal start event is the normal start event declaration with a signalEventDefinition
child-element:
<startEvent id="signal-start-event" name="Start">
<signalEventDefinition id="SignalEventDefinition_00paqo6" (1)
signalRef="signal-one" /> (2)
<outgoing>Flow_0h77bcd</outgoing>
</startEvent>
1 | — Event declaration. |
2 | — Reference to signal definition. |
Using Signal Start Event
When a process is deployed, the engine creates a signal subscription for each signal start event. Subscriptions of the previous version of the process would be closed.
It is allowed to have many process definitions with the signal start event referred to the same signal. When the signal fires, all subscriptions be activated and processes started.
The signal can be 'fired' from within a process instance using the intermediate signal throw event or through the API methods signalEventReceived
.
In API call use exactly signal name, not id. For example, we have such signal definition:
<signal id="ready" name="Ready" flowable:scope="global" />
Then, invoke API method the following way:
runtimeService.signalEventReceived("Ready");
Signal start events are not supported in embedded subprocesses. |
Signal Intermediate Catching Event
Signal intermediate catching event catches signals with the same signal name as the referenced signal subscription. Signal intermediate catching event is a wait state.
An intermediate signal catch event is visualized as a typical intermediate event (circle with double outline), with the signal icon inside. The signal icon is unfilled to indicate its catch semantics.
An intermediate signal catch event properties are the same as for a signal start event.
<intermediateCatchEvent id="signal-catch-event" name="Catch signal">
<incoming>Flow_0qwib28</incoming>
<outgoing>Flow_1itm8do</outgoing>
<signalEventDefinition id="SignalEventDefinition_1" (1)
signalRef="signal-one" /> (2)
</intermediateCatchEvent>
1 | — Signal event declaration. |
2 | — Reference to the signal definition. |
Signal Intermediate Throwing Event
An intermediate throwing signal event throws a signal event for a defined signal. The signal is broadcast to all catching signal events, starting and intermediate (signal subscriptions).
An intermediate signal throw event is visualized as a typical intermediate event (circle with double outline), with the signal icon inside. The signal icon is filled to indicate its throw semantics.
An intermediate signal catch event properties are the same as for a signal start event, but its semantics differs — throwing instead of catching.
Signals Publication Mode
Signals can be published synchronously or asynchronously.
-
In the default configuration, the signal is delivered synchronously. This means that the throwing process instance waits until the signal is delivered to all catching process instances. The catching process instances are also notified in the same transaction as the throwing process instance, which means that if one of the notified instances produces a technical error (throws an exception), all involved instances fail.
-
A signal can also be delivered asynchronously. In this case, it is determined which handlers are active at the time the throwing signal event is reached. For each active handler, an asynchronous notification message (Job) is stored and delivered by the
JobExecutor
.
A signal intermediate event is defined as an intermediate throwing event.
The specific type sub-element is, in this case, a signalEventDefinition
element.
<intermediateThrowEvent id="Event_sync">
<signalEventDefinition id="SignalEventDefinition_14tnjbf"
signalRef="my-signal" /> (1)
</intermediateThrowEvent>
<intermediateThrowEvent id="Event_async">
<signalEventDefinition id="SignalEventDefinition_14tnjbf"
signalRef="my-signal" flowable:async="true" /> (2)
</intermediateThrowEvent>
1 | — Attribute async is omitted, implicitly it is false , the signal will be published synchronously. |
2 | — Signal be published asynchronously. |
Error Events
Error events in BPMN are typically used to model exceptional or error situations that may arise during the execution of a process. They can be attached to activities or subprocesses within a BPMN diagram to define how errors should be handled, such as by triggering error handling routines, logging the error, or notifying stakeholders.
There are the following types of error events:
-
Error start event (in event subprocesses only)
Error Start Event
An error start event can be used to trigger an event subprocess. It cannot be used for starting a process instance. An error start event is always interrupting.
An error start event is visualized as a circle with an error event symbol. The symbol is unfilled, to represent the catching (receiving) behavior.
An error start event has a specific property — Error, that must refer to some error definition.
Unlike messages and signals, reference to error definition isn’t mandatory. If in the event the error definition is omitted, the subprocess will start for every error event that occurs.
The XML representation of an error start event is the normal start event declaration with an errorEventDefinition
child-element:
<startEvent id="error-event" name="Error">
<errorEventDefinition id="ErrorEventDefinition_1" (1)
errorRef="failure" /> (2)
</startEvent>
1 | — Error event declaration. |
2 | — Reference to error definition. |
Error Boundary Event
An error boundary event catches errors that are thrown within the scope of the activity on which it is defined.
An error boundary event is visualized as a typical intermediate event (circle with double outline) on the boundary, with the error icon inside. The error icon is unfilled to indicate its catch semantics.
An error boundary event has the same properties as error start event.
<serviceTask id="Activity_1" name="Check error"
. . .
</serviceTask>
<boundaryEvent id="error-boundary-event" name="Error"
attachedToRef="Activity_1">
<errorEventDefinition id="ErrorEventDefinition_1"
errorRef="failure" />
</boundaryEvent>
Error End Event
When process execution arrives at an error end event, the current process path ends and an error is thrown.
An error end event is visualized as a typical end event (circle with a thick border), with the error icon inside. The error icon is filled to indicate its throwing semantics.
Properties
An error end event has a specific property Error that isn’t mandatory. When filled, it refers to the existing error definition.
An error end event is represented as an end event, with an errorEventDefinition
child element.
<endEvent id="Event_01" name="Error">
<incoming>Flow_1i3jqxp</incoming>
<errorEventDefinition id="ErrorEventDefinition_11xfxfw" (1)
errorRef="failure" /> (2)
</endEvent>
1 | — Declaring error event |
2 | — Reference to the error definition, it can be omitted. |
Using Error End Event
The error end event is a throwing event and must have the corresponding catching event. It can be an error boundary event if the error end event belongs to a subprocess.
Or error start event if there is an event subprocess.
Using error end event without catching error event causes an exception at runtime. |
See more it the Error Handling section.
Compensation Events
Compensation events help with undoing steps that were already successfully completed in the case that their results are no longer desired and need to be reversed.
There are types of compensation events:
Compensation Intermediate Throw Event
Compensation intermediate throwing event can be used to trigger compensation.
Triggering Compensation
Compensation can either be triggered for a designated activity or for the scope that hosts the compensation event. Compensation is performed through execution of the compensation handler associated with an activity.
When compensation is thrown for an activity, the associated compensation handler is executed the same number of times the activity completed successfully.
If compensation is thrown for the current scope, all activities within the current scope are compensated, which includes activities on concurrent branches.
Compensation is triggered hierarchically: if the activity to be compensated is a subprocess, compensation is triggered for all activities contained in the subprocess. If the subprocess has nested activities, compensation is thrown recursively. However, compensation is not propagated to the "upper levels" of the process: if compensation is triggered within a subprocess, it is not propagated to activities outside of the subprocess scope. The BPMN specification states that compensation is triggered for activities at "the same level of subprocess".
In Flowable, compensation is performed in reverse order of execution. This means that whichever activity completed last is compensated first, and so on.
The intermediate throwing compensation event can be used to compensate transaction subprocesses that competed successfully.
An intermediate compensation throw event is visualized as a typical intermediate event (circle with double outline), with the compensation icon inside. The compensation icon is filled to indicate its throw semantics.
A compensation throw event has no specific properties.
A compensation intermediate event is defined as an intermediate throwing event. The specific type sub-element is, in this case, a compensateEventDefinition
element.
<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition id="CompensateEventDefinition_0s3nsqo" />
</intermediateThrowEvent>
In addition, the optional argument activityRef can be used to trigger compensation of a specific scope or activity:
<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition id="CompensateEventDefinition_0s3nsqo"
activityRef="bookHotel" /> (1)
</intermediateThrowEvent>
1 | — Triggering compensation for specific activity. |
Example
If compensation is triggered within a scope that contains a subprocess, and that subprocess includes activities with compensation handlers, the compensation will only be propagated to the subprocess if it has completed successfully at the time the compensation is thrown.
If some activities nested within the subprocess have already completed and have attached compensation handlers, those handlers will not be executed if the subprocess itself has not yet completed. Consider the following example:
In this process, we have two concurrent executions: one for the embedded subprocess and another for the "charge credit card" activity. Let’s assume both executions have started, and the first concurrent execution is currently waiting for the user to complete the "review bookings" task.
The second execution carries out the "charge credit card" activity, during which an error occurs, triggering the "cancel booking" event to initiate compensation.
At this point, the parallel subprocess has not yet completed, meaning the compensation event is not propagated to it, and consequently, the "cancel hotel booking" compensation handler is not executed.
If the user task (and, consequently, the embedded subprocess) is completed before the "cancel booking" action is performed, compensation will be propagated to the embedded subprocess.
Compensation Boundary Event
Compensation boundary event can be used to attach a compensation handler to an activity.
The compensation boundary event must reference a single compensation handler using a directed association.
A compensation boundary event has a different activation policy from other boundary events. Other boundary events, such as the signal boundary event, are activated when the activity they are attached to is started. When the activity is finished, they are deactivated and the corresponding event subscription is canceled.
The compensation boundary event is different. The compensation boundary event is activated when the activity it is attached to completes successfully. At this point, the corresponding subscription to the compensation events is created. The subscription is removed either when a compensation event is triggered or when the corresponding process instance ends. From this, it follows:
-
When compensation is triggered, the compensation handler associated with the compensation boundary event is invoked the same number of times the activity it is attached to completed successfully.
-
If a compensation boundary event is attached to an activity with multiple instance characteristics, a compensation event subscription is created for each instance.
-
If the process instance ends, the subscriptions to compensation events are canceled.
The compensation boundary event is not supported on embedded subprocesses. |
A compensation boundary event is visualized as a typical intermediate event (circle with double outline) on the boundary, with the compensation icon inside. The compensation icon is unfilled to indicate its catching semantics. In addition to a compensation boundary event, the following figure shows a compensation handler associated with the boundary event using a unidirectional association.
The compensation boundary event must reference a single compensation handler using a directed association.
A compensation boundary event is defined as a typical boundary event:
<boundaryEvent id="Event_1" attachedToRef="Activity_1">
<compensateEventDefinition id="CompensateEventDefinition_05" />
</boundaryEvent>
. . .
<association id="Association_02zt79e"
associationDirection="One"
sourceRef="Event_1" targetRef="Activity_1" />
Cancel Events
Cancel events are used in transaction subprocesses only. They are not available in the palette until you are in a transaction subprocess.
There are two types of cancel events:
Cancel End Event
The cancel end event can only be used in combination with a BPMN transaction subprocess. When the cancel end event is reached, a cancel event is thrown which must be caught by a cancel boundary event. The cancel boundary event then cancels the transaction and triggers compensation.
A cancel end event is visualized as a typical end event (circle with thick outline), with the cancel icon inside. The cancel icon is completely black, to indicate its throwing semantics.
A cancel end event is represented as an end event, with a cancelEventDefinition
child element.
<endEvent id="myCancelEndEvent">
<cancelEventDefinition />
</endEvent>
Cancel Boundary Event
An attached intermediate catching cancel event on the boundary of a transaction subprocess, or boundary cancel event for short, is triggered when a transaction is canceled.
When the cancel boundary event is triggered, it first interrupts all active executions in the current scope. Next, it starts compensation for all active compensation boundary events in the scope of the transaction.
Compensation is performed synchronously; in other words, the boundary event waits before compensation is completed before leaving the transaction. When compensation is completed, the transaction subprocess is left using any sequence flows running out of the cancel boundary event.
|
A cancel boundary event is visualized as a typical intermediate event (circle with a double outline) on the boundary, with the cancel icon inside. The cancel icon is unfilled to indicate its catching semantics.
A cancel boundary event is defined as a typical boundary event:
<boundaryEvent id="boundary" attachedToRef="transaction" >
<cancelEventDefinition />
</boundaryEvent>
As the cancel boundary event is always interrupting the cancelActivity
attribute is not required.
Terminate end event
When a terminate end event is reached, all executions of the current process instance or subprocess will be terminated.
A cancel end event visualized as a typical end event (circle with thick outline), with a full black circle inside.
A terminate end event is represented as an end event, with a terminateEventDefinition
child element.
<endEvent id="myEndEvent >
<terminateEventDefinition flowable:terminateAll="true">
</terminateEventDefinition>
</endEvent>
The |
Using Terminate End Event
In this example, we can see two user tasks executed in parallel. If the task #2 to be completed first, the execution arrives to the terminate end event. At this moment, task #1 will be deleted even it is still active.
In the next example, the terminate end event is in a subprocess. When it will be reached, it affects only subprocess. So, task #1 will be deleted if it is active, subprocess be terminated, and the main process be continued a normal way.
BPMN Events Coverage
In Jmix BPM, not all BPMN 2.0 events are supported, and those that are not supported are marked in pink. This indicates that while the BPMN 2.0 standard defines a wide range of events, Jmix BPM integrates the Flowable BPM engine, which may not implement every event type available in the standard.
Not supported events:
-
Message throwing, intermediate and end event
-
Signal throwing end event
-
Compensation end event
-
Escalation events (all types)
-
Conditional events (all types)
-
Link events (all types)
Be careful when importing BPMN models from 3rd party design tools: not supported events can be shown on the diagram but may cause error at runtime. |
Workarounds for Unsupported Events
In this section, you’ll find recipes how to implement a desired process logic for elements that are not supported in Jmix BPM.
Message Throwing Event
First, use signals instead of messages everywhere it is possible. In most cases, these types of events are interchangeable.
Second, use a service task with the API call.
Service task can be implemented as Spring bean, for example:
@Component(value = "smpl_MyService")
public class MyService {
@Autowired
private RuntimeService runtimeService;
public void sendMessage(String messageName, String executionId) {
runtimeService.messageEventReceived(messageName, executionId);
}
}
Signal Throwing End Event
Use the combination of signal throwing intermediate event and none_end_event:
Escalation Events
It is possible to use BPMN error events instead of escalation in certain scenarios. Error events in BPMN are used to handle unexpected errors or exceptions that occur during the execution of a process. They can be used to model error handling and recovery mechanisms within a process.
Escalation events, on the other hand, are used to escalate a problem to a higher level in the organization or process hierarchy. They are typically used when a problem cannot be resolved at the current level and needs to be escalated for further action.
So, escalation events are technically very close to error events.
Conditional Events
The conditional event defines an event which is triggered if a given condition is evaluated to true. It can be used as start event of an event subprocess, as intermediate event and boundary event. The start and boundary event can be interrupting and non interrupting.
You can implement similar logic by using execution listeners in combination with signal or message event.