Events
An event is something that happens while a process runs: a timer fires, a message arrives, a step fails with a business error. Events start and end paths, make the process wait, and change its path.
Event Element Types
An event has a position in the process and a trigger. By position, an event is one of the following:
-
A start event starts a process instance or a subprocess. In an event subprocess, its trigger starts the event subprocess.
-
An intermediate event is on a sequence flow between two elements.
-
A boundary event is attached to an activity: a task, a subprocess, or a call activity. It reacts to its trigger while the activity runs. A compensation boundary event is the exception: it becomes active when the activity completes. In the Modeler view, drag an intermediate event from the palette onto the border of an activity to attach it.
-
An end event ends a path.
By trigger, an event is a none, timer, message, signal, error, escalation, compensation, cancel, or terminate event. The table below shows which triggers are available in which position.
A catching event waits for its trigger. Start events, boundary events, and intermediate catching events are catching events. A throwing event creates a trigger for catching events, for example, throws an error or a signal. Intermediate throwing events and end events are throwing events, but none events throw nothing.
An intermediate catching event is a wait state: the process stops there, the engine commits the transaction and stores the process state, and the process continues when the trigger arrives. The engine waits for messages and signals through event subscriptions and for timers through timer jobs.
Boundary events and the start events of event subprocesses can be interrupting or non-interrupting. Error and cancel events are always interrupting.
-
An interrupting boundary event cancels the activity, and the process continues along the outgoing sequence flow of the event.
-
An interrupting start event of an event subprocess cancels everything else in its scope. When the event subprocess completes, the scope completes too.
-
A non-interrupting event starts its path in parallel, and the activity or the scope keeps running.
The scope of an event is the process instance or the subprocess that contains it. When an error or an escalation is thrown, the engine looks for a catching event in the scope of the throwing event first, and then in the enclosing scopes.
The following table shows the events by trigger and position:
| Trigger | Start | Intermediate Catching | Intermediate Throwing | Boundary | End |
|---|---|---|---|---|---|
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|
||
|
|||||
|
|
||||
|
|
|
|
||
|
| Not all BPMN 2.0 events are supported in Jmix BPM. See BPMN Events Coverage. |
Choosing an Event
| To | Use |
|---|---|
Start a process from the Start process view or from code |
|
Start a process on a schedule |
|
Pause a process for some time or until a date |
|
Remind the assignee or take further steps when a task takes too long |
Timer boundary event: non-interrupting to keep the task, interrupting to cancel it |
Start a process when your code sends a named message |
|
Wait until your code reports something about one process instance, such as a received payment |
Message intermediate catching event or message boundary event |
Notify many process instances at once, such as about a changed price list |
|
Leave the normal path because of a business failure, such as a declined payment |
|
Report a situation to an enclosing scope, with or without stopping the work |
|
Undo steps that have completed |
|
Cancel a transaction subprocess and undo its completed steps |
|
Stop all parallel paths when one path finishes |
|
Mark a milestone |
Some events are easy to confuse:
-
Message or signal. A message goes to one execution that your code selects, or starts one process. A signal goes to every event that waits for it. Use a signal only when all waiting process instances must react.
-
Error or escalation. An error always interrupts, and if no event catches it, the engine throws an exception. An escalation can be caught without interrupting, and if no event catches it, the engine ignores it.
-
None end event or terminate end event. A none end event ends only its own path, and parallel paths go on. A terminate end event ends all paths in its scope.
-
Error or compensation. An error moves the process to another path. Compensation undoes steps that have already completed, usually on that other path.
Event Subscriptions
An event subscription is a record that tells the process engine that a process waits for a message or a signal. Only message and signal events wait through subscriptions. Timers use timer jobs, see Timer Events. Error and escalation events need neither: the engine looks for a catching event when an error or an escalation is thrown.
The engine creates subscriptions as follows:
-
Start events – a message or signal start event of a process gets a subscription when the process definition is deployed. When the message or signal arrives, a new process instance starts.
-
Intermediate events / boundary events – a message or signal catching event gets a subscription when the process arrives at the event or, for a boundary event, when the activity it is attached to starts. When the message or signal arrives, the engine finds the matching subscription, and the execution continues.
The engine stores subscriptions in the ACT_RU_EVENT_SUBSCR database table.
Event Subscriptions API
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 message subscriptions, use "message". The engine also keeps "compensate" subscriptions for completed activities that have a compensation handler.
For timers, use ManagementService:
List<Job> timerJobs = managementService.createTimerJobQuery().list();
Triggering Event Subscriptions
You can trigger event subscription when the corresponding event occurs. For example, to trigger a message event:
runtimeService.messageEventReceived("orderPlaced", executionId, processVariables);
Handling Events with Listeners
See the Event Listeners section.
None Events
A none event has no trigger. Most processes start with a none start event and end with none end events. See None Start Event and Intermediate Throwing None Event in the Flowable documentation.
| Event | Usage |
|---|---|
Starts a process instance when a user starts the process in the Start process view or code calls |
|
The process passes through the event without waiting. Use it to mark a state that the process has reached, such as a milestone. |
|
Ends the current path. The process instance ends when no paths are active. |
None Event Properties
In the Modeler view, you can set the following properties of none events:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Form |
The user interface shown when the process is started manually. See Process Forms. |
Process variables |
Parameters used for starting the process via API. Available when no form is set. |
Execution listeners |
Start events only. See Execution Listeners. |
Asynchronous execution |
Since Jmix 3.1 |
Documentation |
A description and additional information about the element. |
A none start event has all these properties. In a subprocess, it has no Form. A none end event has Id, Name, Asynchronous and Exclusive, and Documentation. A none intermediate throwing event has only Id and Name.
Example
In this example, the Address validated none intermediate throwing event marks that the Validate address task has completed. The process passes through the event to the Send parcel task.
The XML of this example:
<process id="parcel-delivery" isExecutable="true">
<startEvent id="start" /> (1)
. . .
<serviceTask id="validate-address" name="Validate address" ... />
. . .
<intermediateThrowEvent id="address-validated" name="Address validated" /> (2)
. . .
<endEvent id="end" /> (3)
</process>
| 1 | A none start event has no event definition. |
| 2 | A none intermediate throwing event. |
| 3 | A none end event. |
Timer Events
A timer event fires at a date, after a duration, or on a repeating cycle. Use timers to start processes on a schedule, to pause a process, and to set deadlines and reminders on tasks. The job executor runs the timers. See Timer Event Definitions in the Flowable documentation.
To add a timer event in the Modeler view, click the Change type
icon of a start, intermediate, or boundary event and select a timer option.
| Event | Usage |
|---|---|
Starts a process instance when the timer fires. A cycle timer starts an instance on each occurrence. The engine creates the timer when the process is deployed, and deploying a new version of the process replaces it. A process started by a timer has no In an event subprocess, starts the event subprocess and can be interrupting or non-interrupting. An embedded subprocess can’t have a timer start event. |
|
The process waits at the event until the timer fires. The event is a wait state. |
|
Fires if the activity it is attached to is still active when the timer fires. Can be interrupting or non-interrupting. |
Timer Values
| Timer type | Value | Examples |
|---|---|---|
Duration |
An ISO 8601 duration. For a start event, the engine counts it from the deployment. For other timer events, it counts from the moment the process reaches the event or the activity that the event is attached to. |
|
Date |
An ISO 8601 date and time. If the date has passed, the timer fires right away. |
|
Cycle |
An ISO 8601 repeating interval or a cron expression. The first field of a cron expression is seconds. |
|
A value can be an expression that returns such a string, for example, ${reviewPeriod}. Use cron expressions only with the Cycle type. With other types, the engine can’t create the timer and throws an exception: couldn’t resolve duedate.
Timer Event Properties
In the Modeler view, you can set the following properties of timer events:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Timer type |
Duration, Date, or Cycle. See Timer Values. |
Duration, Date, Cycle |
The timer value for the selected type. |
Business calendar |
The business calendar used to calculate the timer. Available if the Business Calendars add-on is installed. |
Execution listeners |
Start events only. See Execution Listeners. |
Asynchronous execution |
Since Jmix 3.1 |
Documentation |
A description and additional information about the element. |
Intermediate and boundary timer events have no Execution listeners and Documentation. A timer start event also shows the Process variables section, like the none start event.
Example
In this example, the process starts every Monday at 9:00. The Write report user task has two timer boundary events. After an hour, the non-interrupting 1 hour event creates the Remind performer task, and Write report stays active. After five days, the interrupting 5 days event cancels Write report and creates the Escalate issue task. When the report is written, the Next day event holds the process for a day before the Check report task.
The XML of this example:
<process id="weekly-report" isExecutable="true">
<startEvent id="every-week" name="Every week">
<timerEventDefinition>
<timeCycle>0 0 9 ? * MON</timeCycle> (1)
</timerEventDefinition>
</startEvent>
. . .
<userTask id="write-report" name="Write report" />
<boundaryEvent id="one-hour" name="1 hour" attachedToRef="write-report"
cancelActivity="false"> (2)
<timerEventDefinition>
<timeDuration>PT1H</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<boundaryEvent id="five-days" name="5 days" attachedToRef="write-report"> (3)
<timerEventDefinition>
<timeDuration>P5D</timeDuration>
</timerEventDefinition>
</boundaryEvent>
. . .
<intermediateCatchEvent id="next-day" name="Next day">
<timerEventDefinition>
<timeDuration>P1D</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
. . .
</process>
| 1 | A cron expression: every Monday at 9:00. |
| 2 | A non-interrupting boundary event. |
| 3 | An interrupting boundary event. Omitting cancelActivity is the same as setting it to true. |
Message Events
A message event waits for a message that your code sends to a process instance, or starts a process instance when the message arrives. Use it when another system or your application must tell one specific process instance that something has happened, for example, that a payment has arrived. See Message Event Definitions in the Flowable documentation.
To add a message event in the Modeler view, click the Change type
icon of a start, intermediate, or boundary event and select a message option.
| Event | Usage |
|---|---|
Starts a process instance when your code sends the message. In an event subprocess, starts the event subprocess when the process instance receives the message, and can be interrupting or non-interrupting. An embedded subprocess can’t have a message start event. |
|
The process waits at the event until it receives the message. The event is a wait state. |
|
Catches the message while the activity it is attached to is active. Can be interrupting or non-interrupting. |
Jmix BPM doesn’t support message intermediate throwing events and message end events. See Message Throwing Event.
Sending Messages
Message events refer to message definitions of the process. A definition has an id and a name. You can manage definitions in the process properties or add one from an event by selecting Create new… in its Message field.
Your code sends messages through RuntimeService and passes the message name, not the id:
-
startProcessInstanceByMessage(messageName)starts a process instance at a message start event. If no deployed process has a start event for the message, the call fails withno subscription to message with name … found. A message can start only one process: deploying another process with a start event for the same message fails withthere already is a message event subscription for the message with name …. -
messageEventReceived(messageName, executionId)delivers the message to an execution that waits for it. If the execution doesn’t wait for the message, the call fails withdoes not have a subscription to a message event with name …. Find the execution by the message name:Execution execution = runtimeService.createExecutionQuery() .processInstanceId(processInstanceId) .messageEventSubscriptionName("Payment received") .singleResult(); runtimeService.messageEventReceived("Payment received", execution.getId());
Both methods have variants that also pass process variables. After the message, the process runs in the transaction of the call until the next wait state. If a following step throws an exception, the call fails, and the process stays at the event. See Throwing a Message Event in the Flowable documentation.
Message Event Properties
In the Modeler view, you can set the following properties of message events:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Message |
The message definition the event refers to. If it is empty, the process fails to deploy with |
Execution listeners |
Start events only. See Execution Listeners. |
Asynchronous execution |
Since Jmix 3.1 |
Documentation |
A description and additional information about the element. |
Intermediate and boundary message events have no Execution listeners and Documentation. A message start event also shows the Process variables section, like the none start event.
Example
In this example, the process waits at the message intermediate catching event after Activity 1. When your code delivers the Payment received message to the waiting execution, as shown in Sending Messages, the process continues to Activity 2.
The XML of this example:
<definitions ...>
<message id="payment-received" name="Payment received" /> (1)
<process id="order-processing" isExecutable="true">
. . .
<intermediateCatchEvent id="payment-received-catch">
<messageEventDefinition messageRef="payment-received" /> (2)
</intermediateCatchEvent>
. . .
</process>
</definitions>
| 1 | The message definition. Code refers to the message by its name. |
| 2 | The catching event refers to the definition by its id. |
Signal Events
A signal event throws a signal or catches it. A thrown signal reaches every event that waits for it: in all process instances, or only in the same process instance if the signal has the Process instance scope. Use signals to tell many process instances at once that something has happened, for example, that a shop has closed. See Signal Event Definitions in the Flowable documentation.
To add a signal event in the Modeler view, click the Change type
icon of a start, intermediate, or boundary event and select a signal option.
| Event | Usage |
|---|---|
Starts a process instance when the signal is thrown. If several processes have a start event for the signal, each of them starts. In an event subprocess, starts the event subprocess and can be interrupting or non-interrupting. An embedded subprocess can’t have a signal start event. |
|
The process waits at the event until the signal is thrown. The event is a wait state. |
|
Signal boundary event |
Catches the signal while the activity it is attached to is active. Can be interrupting or non-interrupting. |
Throws the signal. Then the process continues along the outgoing sequence flow. |
Jmix BPM doesn’t support signal end events. See Signal Throwing End Event.
Throwing Signals
Signal events refer to signal definitions of the process. A definition has an id, a name, and a scope. You can manage definitions in the process properties or add one from an event by selecting Create new… in its Signal field.
Your code throws a signal through RuntimeService and passes the signal name, not the id:
runtimeService.signalEventReceived("Shop closed");
The engine delivers a signal in the transaction of the code or process instance that throws it. If a catching process instance fails with an exception, the throwing side fails too, and its transaction rolls back. To deliver a signal asynchronously, set flowable:async="true" on the signalEventDefinition element of a throwing event in XML. The Asynchronous property only makes the event itself asynchronous. See Throwing a Signal Event in the Flowable documentation.
Signal Event Properties
In the Modeler view, you can set the following properties of signal events:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Signal |
The signal definition the event refers to. If it is empty, the process fails to deploy with |
Execution listeners |
Start events only. See Execution Listeners. |
Asynchronous execution |
Since Jmix 3.1 |
Documentation |
A description and additional information about the element. |
Intermediate and boundary signal events have no Execution listeners and Documentation. A signal start event also shows the Process variables section, like the none start event.
Example
In this example, the Shop closed signal boundary event interrupts the Prepare order task, and the process goes to the Cancel order task. The signal has the global scope, so one call of signalEventReceived("Shop closed") cancels the orders in all process instances that wait at Prepare order.
The XML of this example:
<definitions ...>
<signal id="shop-closed" name="Shop closed" flowable:scope="global" /> (1)
<process id="order-processing" isExecutable="true">
. . .
<userTask id="prepare-order" name="Prepare order" />
<boundaryEvent id="shop-closed-catch" name="Shop closed"
attachedToRef="prepare-order">
<signalEventDefinition signalRef="shop-closed" /> (2)
</boundaryEvent>
. . .
</process>
</definitions>
| 1 | The signal definition with the global scope. |
| 2 | The boundary event refers to the definition by its id. |
Error Events
An error event throws or catches a BPMN error: a business error that the process handles on an alternative path, for example, a declined payment. Catching error events are always interrupting. Java code throws a BPMN error as BpmnError. Error events don’t catch other exceptions, which roll back the transaction to the last wait state. See Error Event Definitions in the Flowable documentation and Error Handling.
To add an error event in the Modeler view, click the Change type
icon of an end event, a boundary event, or a start event inside an event subprocess, and select an error option.
| Event | Usage |
|---|---|
Starts an event subprocess when an error is thrown in the scope that contains the event subprocess. The option is available only for start events inside an event subprocess. |
|
Catches errors thrown inside the activity it is attached to: by an error end event in a subprocess, or by Java code that a service task calls. Cancels the activity, and the process continues along the outgoing sequence flow of the event. |
|
Throws the error and ends the current path. |
Matching Errors
Error events refer to error definitions of the process. A definition has an id, a name, and an optional error code. You can manage definitions in the process properties or add one from an event by selecting Create new… in its Error field.
The engine matches throwing and catching events by error code:
-
An event with no error set, or with an error definition that has no code, catches any error.
-
A throwing event with an error definition that has no code matches any catching event, so set a code for the errors that you throw.
-
If an activity has several matching boundary events, the event with the same code takes precedence over a catch-all event.
-
An error end event must refer to an error definition. Otherwise, the process fails when it reaches the event, with
Error Code must not be null. -
Errors that Java code throws, such as
new BpmnError("PAYMENT_FAILED"), are matched by their code in the same way. -
If no event catches the error, the engine throws an exception:
No catching boundary event found for error with errorCode ….
Error Event Properties
In the Modeler view, you can set the following properties of error events:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Error |
The error definition the event throws or catches. Leave it empty on a catching event to catch any error. |
Execution listeners |
See Execution Listeners. |
Asynchronous execution |
Since Jmix 3.1 |
Documentation |
A description and additional information about the element. |
An error start event also shows the Process variables section, like the none start event. Error end events have no Asynchronous leave and Asynchronous leave exclusive properties.
Example
In this example, the error end event of the subprocess throws the Failure error after the Do something task. The error boundary event cancels the subprocess, and the process continues to the Handle error task.
The XML of this example:
<definitions ...>
<error id="failure" name="Failure" errorCode="FAILURE" /> (1)
<process id="error-handling" isExecutable="true">
<subProcess id="subprocess">
. . .
<endEvent id="error-end">
<errorEventDefinition errorRef="failure" /> (2)
</endEvent>
</subProcess>
<boundaryEvent id="error-catch" attachedToRef="subprocess">
<errorEventDefinition errorRef="failure" /> (3)
</boundaryEvent>
. . .
</process>
</definitions>
| 1 | The error definition. |
| 2 | The error end event refers to the definition. |
| 3 | The boundary event catches errors with the FAILURE code. |
Escalation Events
Since Jmix 3.1
An escalation event reports a situation to an enclosing scope, which can react to it with or without interrupting the work in progress.
You can create escalation events in the Modeler view, set their properties, and manage escalation definitions. To add an escalation event, click the Change type
icon of an intermediate, end, or boundary event, or of a start event inside an event subprocess, and select an escalation option.
| Event | Usage |
|---|---|
Escalation start event |
Starts an event subprocess when an escalation is thrown in the scope that contains the event subprocess. Can be interrupting or non-interrupting. The option is available only for start events inside an event subprocess. |
Escalation boundary event |
Catches escalations thrown inside the activity it is attached to, for example, an embedded subprocess. Can be interrupting or non-interrupting. |
Escalation intermediate throwing event |
Throws the escalation. Then the process continues along the outgoing sequence flow, unless an interrupting event has caught the escalation and canceled the enclosing scope. |
Escalation end event |
Throws the escalation and ends the current path. |
Matching Escalations
Escalation events refer to escalation definitions of the process. A definition has an id, a name, and an optional escalation code. You can manage definitions in the process properties or add one from an event by selecting Create new… in its Escalation field.
The engine matches throwing and catching events by escalation code:
-
It looks for a catching event in the scope of the throwing event first, and then in the enclosing scopes.
-
An event with no escalation set, or with an escalation definition that has no code, matches any escalation.
-
If an activity has several matching boundary events, the event with the same code takes precedence over a catch-all event. An event subprocess inside an activity takes precedence over a boundary event attached to that activity.
-
If no event catches the escalation, the engine ignores it. An uncaught error, in contrast, causes an exception at runtime.
Escalation Event Properties
In the Modeler view, you can set the following properties of escalation events:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Escalation |
The escalation definition the event throws or catches. Leave it empty on a catching event to catch any escalation. |
Execution listeners |
See Execution Listeners. |
Asynchronous execution |
|
Documentation |
A description and additional information about the element. |
An escalation start event also shows the Process variables section, like other start events. Escalation end events have no Asynchronous leave and Asynchronous leave exclusive properties.
Example
In this example, the Process order subprocess throws the Low stock escalation after the Reserve items task. The non-interrupting boundary event catches the escalation and creates the Reorder items task. At the same time, the subprocess goes on to the Ship order task.
The XML of this example:
<definitions ...>
<escalation id="low-stock" name="Low stock" escalationCode="LOW_STOCK" /> (1)
<process id="order-processing" isExecutable="true">
<subProcess id="process-order" name="Process order">
. . .
<intermediateThrowEvent id="low-stock-throw" name="Low stock">
<escalationEventDefinition escalationRef="low-stock" /> (2)
</intermediateThrowEvent>
. . .
</subProcess>
<boundaryEvent id="low-stock-catch" name="Low stock"
attachedToRef="process-order" cancelActivity="false"> (3)
<escalationEventDefinition escalationRef="low-stock" />
</boundaryEvent>
. . .
</process>
</definitions>
| 1 | The escalation definition. |
| 2 | The throwing event refers to the definition. |
| 3 | A non-interrupting boundary event. For an interrupting event, omit cancelActivity or set it to true. A non-interrupting escalation start event has isInterrupting="false". |
Compensation Events
Compensation undoes the work of activities that have completed, for example, cancels a hotel booking when the payment fails. A compensation throwing event runs the compensation handlers of these activities. See Compensation Intermediate Throwing Event and Compensation Boundary Event in the Flowable documentation.
To add a compensation event in the Modeler view, click the Change type
icon of an intermediate or boundary event and select Compensation intermediate throw event or Compensation boundary event. To get a boundary event, drag an intermediate event from the palette onto the border of the activity.
| Event | Usage |
|---|---|
Attaches a compensation handler to an activity. To add the handler, click Append compensation activity in the context pad of the event. The Modeler view adds a task marked as a compensation handler and connects it to the event with an association. Change the task type as needed, for example, to a service task. The event becomes active when the activity completes, and the handler runs once for each completion, for example, for each instance of a multi-instance activity. Flowable doesn’t support compensation boundary events on embedded subprocesses: their handlers don’t run. |
|
Runs the compensation handlers of the completed activities in its scope: the process instance, or the subprocess that contains the event. Activities inside a subprocess are compensated only if the subprocess has completed. The handlers run in reverse order of completion; activities that completed in the same transaction can be compensated in any order. Then the process continues along the outgoing sequence flow. To compensate one activity only, set the |
|
Compensation start event |
The Modeler view offers this option for start events inside an event subprocess, but Flowable doesn’t support it: a process with such an event fails to deploy with |
In the Modeler view, compensation events have only the Id and Name properties.
Example
In this example, the Book hotel multi-instance task in the subprocess has a compensation boundary event with the Cancel hotel booking handler. If the Charge credit card task throws an error, its error boundary event leads to the Cancel booking compensation throwing event, which compensates the completed activities of the process:
-
If the subprocess has completed,
Cancel hotel bookingruns once for each completed instance ofBook hotel. -
If the subprocess is still active, for example, at the
Review bookingtask, compensation doesn’t reach the activities inside it, andCancel hotel bookingdoesn’t run.
The XML of this example:
<process id="booking" isExecutable="true">
. . .
<subProcess id="booking-subprocess">
. . .
<serviceTask id="book-hotel" name="Book hotel" ...>
<multiInstanceLoopCharacteristics ... />
</serviceTask>
<boundaryEvent id="book-hotel-compensation" attachedToRef="book-hotel">
<compensateEventDefinition /> (1)
</boundaryEvent>
<serviceTask id="cancel-hotel-booking" name="Cancel hotel booking"
isForCompensation="true" ... /> (2)
. . .
<association id="compensation-association" associationDirection="One"
sourceRef="book-hotel-compensation" targetRef="cancel-hotel-booking" /> (3)
</subProcess>
. . .
<intermediateThrowEvent id="cancel-booking" name="Cancel booking">
<compensateEventDefinition /> (4)
</intermediateThrowEvent>
. . .
</process>
| 1 | The compensation boundary event. |
| 2 | The compensation handler. |
| 3 | The association that connects the event and the handler. |
| 4 | The compensation throwing event. It compensates all completed activities in its scope, which is the process. |
Cancel Events
Cancel events cancel a transaction subprocess. See Cancel End Event and Cancel Boundary Event in the Flowable documentation.
To add a cancel event in the Modeler view, click the Change type
icon of an end event inside a transaction subprocess or of a boundary event on it, and select a cancel option.
| Event | Usage |
|---|---|
Cancels the transaction subprocess that contains the event. Outside a transaction subprocess, for example, in a model from another tool, the process fails to deploy with |
|
Catches the cancellation on the boundary of the transaction subprocess. It interrupts the transaction, runs compensation for the activities of the transaction that have completed, and then the process continues along the outgoing sequence flow of the event. A transaction subprocess can have only one cancel boundary event. |
For an example, see Possible Outcomes of a Transaction.
Cancel Event Properties
In the Modeler view, you can set the following properties of a cancel end event:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Asynchronous execution |
|
Documentation |
A description and additional information about the element. |
A cancel boundary event has only the Id and Name properties.
Terminate End Event
A terminate end event ends all paths in its scope: the process instance or, inside a subprocess, the subprocess. Use it when one path decides the outcome and the other paths must stop, for example, when an order is canceled while other tasks are still open. See Terminate End Event in the Flowable documentation.
To add a terminate end event in the Modeler view, click the Change type
icon of an end event and select Terminate end event.
Terminate End Event Properties
In the Modeler view, you can set the following properties of a terminate end event:
Property |
Description |
Id |
The identifier of the element. It is generated automatically, but you can change it to a more meaningful one to make logs easier to understand. |
Name |
The name of the element. |
Terminate all |
If selected, the event ends the whole process instance, even if the event is inside a subprocess. Not selected by default. |
Execution listeners |
See Execution Listeners. |
Asynchronous execution |
|
Documentation |
A description and additional information about the element. |
Example
In this example, when Task 2 completes, the terminate end event ends the subprocess: Task 1 is canceled, and the process continues to Task 3. Task 0 stays active. With Terminate all selected, the event ends the whole process instance, including Task 0.
The XML of this example:
<subProcess id="subprocess">
. . .
<endEvent id="terminate-end" name="Terminate end event">
<terminateEventDefinition /> (1)
</endEvent>
</subProcess>
| 1 | With Terminate all selected, the element has the flowable:terminateAll="true" attribute. |
BPMN Events Coverage
Jmix BPM doesn’t support all BPMN 2.0 events. In the diagram below, unsupported events are marked in pink.
The following events are not supported:
-
Conditional events of all types
-
Link events
-
Message intermediate throwing events and message end events
-
Signal end events
-
Compensation start events and compensation end events
The Modeler view doesn’t offer these events. The exception is compensation start events, which it offers inside event subprocesses, although a process with such an event fails to deploy. Conditional events are implemented in the Flowable engine but not supported in Jmix BPM. The other events are not implemented in Flowable either. See Workarounds for Unsupported Events for ways to model similar logic.
|
A BPMN model created in another tool can contain unsupported events. The Modeler view shows them on the diagram, but some of them don’t work as the BPMN specification defines:
|
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:
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.





