Skip to main content

Process messaging

This chapter focuses on using message and signal events for process communication within the tSM Process Engine, which is based on the BPMN 2.0 standard. It provides an in-depth look at how messages and signals can be used to orchestrate and continue process executions, both within a single process instance and across multiple processes or external systems.

Introduction

In the tSM Process Engine, there are three primary ways to continue a process execution:

  1. Job-based continuation: A job (e.g., a timer event, asynchronous continuation) triggers the next step.
  2. User or system task completion: A human or automated system completes a task, moving the process forward.
  3. Receiving an event (message or signal): The process waits for an event and proceeds when that event is received.

This documentation focuses on approach #3: events (messages and signals).

Key Differences:

  • Messages are usually directed to a single recipient. Messages typically require a correlation key (e.g., a business key or some process variable) to identify the waiting process instance.
  • Signals are broadcast to all active listeners. Every process instance waiting for a particular signal name will be notified simultaneously.

Event sources can be:

  • Internal BPMN flows: Events triggered from within the same process or subprocess.
  • Inter-process communication: One process instance sends a message or throws a signal to affect another process instance.
  • External systems: Events generated via external APIs (such as tSM Services REST API) or event-driven architectures (e.g., Kafka).

Common Use Cases

  • Subprocess-to-subprocess messaging: After a field technician completes a device installation, a message triggers a network configuration subprocess.
  • Asynchronous communication with external systems: An external service completes its work and sends a message event back into the engine. This can be done using REST, Kafka, JMS, etc.
  • Dynamic task instantiation: Start ad hoc subprocesses based on user actions or business conditions.
  • Process cancellation or compensation: Trigger a cancellation subprocess via message or signal events.
  • Broadcast notifications: Use signals to notify multiple process instances simultaneously, for scenarios like business rule changes.

Message Events

Message events represent directed, point-to-point communication. They require a named message definition and are correlated to a specific process instance or definition.

Defining a Message

Messages are defined at the definitions level in your BPMN file. A message has an id and a name. BPMN elements that use this message reference it via messageRef.

<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:camunda="http://activiti.org/bpmn"
targetNamespace="Examples"
xmlns:tns="Examples">

<message id="newInvoice" name="newInvoiceMessage" />
<message id="payment" name="paymentMessage" />

<process id="invoiceProcess">
<startEvent id="messageStart">
<messageEventDefinition messageRef="newInvoice" />
</startEvent>

<intermediateCatchEvent id="paymentEvt">
<messageEventDefinition messageRef="payment" />
</intermediateCatchEvent>
...
</process>
</definitions>

Message Start Events

A Message Start Event triggers a new process instance when the engine receives a message that matches the event’s message name. The message name must be static for the main process start. Using message start events is useful when you expect external triggers to initiate new process instances.

Expressions in Message Names

You can use expressions in message names (for intermediate events), resolving the final message name at runtime. This allows for dynamic correlation based on process variables.

<message id="dynamicMsg" name="baseMessage-${execution.processBusinessKey}" />

Note:

  • Expressions are not allowed in the start event of the main process definition.
  • Allowed for message start events of subprocesses and intermediate message catching events.

Message Correlation in Camunda

To deliver a message to the engine, you typically use the Camunda RuntimeService or the REST API.

runtimeService.correlateMessage("newInvoiceMessage", "businessKey123", variables);

Using REST API:

POST /engine-rest/message
{
"messageName" : "newInvoiceMessage",
"businessKey" : "businessKey123",
"processVariables" : {
"var1" : { "value": "someValue", "type": "String" }
}
}

The engine attempts to find a waiting event subscription that matches the messageName and correlates it to the correct process instance.

Message Intermediate Catching Event

A Message Intermediate Catching Event suspends the process until a message arrives. Once correlated, the process resumes.

<intermediateCatchEvent id="messageWait">
<messageEventDefinition messageRef="newCustomerMessage" />
</intermediateCatchEvent>

Alternatives:

  • Receive Task: Waits for a message, similar usage.
  • Event-based Gateway: Used to model a scenario where the process waits for one of several possible messages or events.

Message Boundary Event

A Message Boundary Event attaches to an activity and listens for a message while the activity is running. When the message arrives:

  • Interrupting event: Cancels the activity and proceeds along the boundary event’s outgoing flow.
  • Non-interrupting event: Keeps the activity running and spawns an additional execution path.
<boundaryEvent id="messageBoundary" attachedToRef="someTask" cancelActivity="true">
<messageEventDefinition messageRef="overrideInstructionMessage" />
</boundaryEvent>

Message Intermediate Throwing Event

A Message Intermediate Throwing Event sends a message to an external service. It behaves like a service task and requires an implementation (delegate, connector, etc.).

<intermediateThrowEvent id="sendNotification">
<messageEventDefinition camunda:class="org.camunda.bpm.MyMessageServiceDelegate" />
</intermediateThrowEvent>

Message End Event

A Message End Event sends a message and then ends the current execution path. Similar to the intermediate throwing event, but it concludes the sequence flow.

<endEvent id="endWithMessage">
<messageEventDefinition camunda:class="org.camunda.bpm.MyMessageServiceDelegate" />
</endEvent>

Signal Events

Signal events are broadcast globally within the engine. Any process instance waiting for a given signal is notified simultaneously. Signals do not require correlation keys.

Defining a Signal

Like messages, signals are defined in the definitions section.

<definitions>
<signal id="alertSignal" name="alert" />

<process id="signalExample">
<intermediateThrowEvent id="throwSignalEvent" name="Raise Alert">
<signalEventDefinition signalRef="alertSignal" />
</intermediateThrowEvent>

<intermediateCatchEvent id="catchSignalEvent" name="On Alert">
<signalEventDefinition signalRef="alertSignal" />
</intermediateCatchEvent>
</process>
</definitions>

Broadcasting a Signal

When a signal is thrown, all waiting signal events with that signal name are triggered. Unlike messages, you do not specify a particular recipient.

Expressions in Signal Names

You can use expressions in the signal name for dynamic naming at runtime.

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

Signal Intermediate Catching Event

A Signal Intermediate Catching Event waits until a signal with the given name is broadcast.

<intermediateCatchEvent id="waitForAlert">
<signalEventDefinition signalRef="alertSignal" />
</intermediateCatchEvent>

Signal Boundary Event

A Signal Boundary Event attaches to an activity and listens for a signal. Once the signal is broadcast:

  • If the boundary event is interrupting, it cancels the activity.
  • If non-interrupting, it spawns a new execution path.
<boundaryEvent id="signalBoundary" attachedToRef="taskId" cancelActivity="true">
<signalEventDefinition signalRef="alertSignal"/>
</boundaryEvent>

Throwing Signals

Signal Intermediate Throwing Event:

<intermediateThrowEvent id="broadcastAlert">
<signalEventDefinition signalRef="alertSignal" />
</intermediateThrowEvent>

To make it asynchronous:

<intermediateThrowEvent id="broadcastAlertAsync">
<signalEventDefinition signalRef="alertSignal" camunda:asyncBefore="true" />
</intermediateThrowEvent>

Signal End Event:

<endEvent id="endAndBroadcastAlert">
<signalEventDefinition signalRef="alertSignal" />
</endEvent>

Asynchronous Signal Delivery

  • Synchronous delivery: The throwing instance waits until all catchers are notified. If any fail, the transaction can roll back.
  • Asynchronous delivery: When camunda:asyncBefore="true" is used, the signal throw is handled as a separate job, isolating failures and providing better fault-tolerance.

External Triggering via tSM Services API

External systems can use the tSM Services API to send messages or signals into the engine. For messages:

POST /engine-rest/message
Content-Type: application/json

{
"messageName": "newInvoiceMessage",
"businessKey": "customer123",
"processVariables": {
"amount": {"value": 100, "type":"Integer"},
"customerStatus": {"value":"VIP", "type":"String"}
}
}

For signals, using Camunda’s REST API:

POST /engine-rest/signal
Content-Type: application/json

{
"name": "alertSignal",
"variables": {
"cause": {"value":"maintenance", "type":"String"}
}
}

Best Practices and Considerations

  • Use messages for targeted communication: Messages are ideal when you know which specific process instance should receive the event.
  • Use signals for broadcast scenarios: Signals are useful for notifying multiple processes at once.
  • Correlation keys: For messages, ensure you have a reliable and consistent correlation mechanism.
  • Error handling and transactions: Consider asynchronous throws for signals to isolate fault conditions.
  • Naming conventions: Clear and meaningful names for messages and signals improve model readability.

Conclusion

Message and signal events provide powerful capabilities for event-driven process orchestration in the tSM Process Engine. Understanding how to define, throw, catch, and correlate these events allows building flexible, decoupled, and scalable workflows that respond dynamically to business events and external triggers.