Zeebe supports FEEL v1.11 – the “Friendly Enough Expression Language” – to express dynamic behavior in your processes.
You can use FEEL expressions in a number of places in your BPMN models.
From the Zeebe documentation:
The following attributes of BPMN elements require an expression:
- Sequence Flow on an Exclusive Gateway: condition
- Message Catch Event / Receive Task: correlation key
- Multi-Instance Activity: input collection, output element
- Input/Output Variable Mappings: source
Additionally, the following attributes of BPMN elements can define an expression optionally instead of a static value:
- Timer Catch Event: timer definition
- Message Catch Event / Receive Task: message name
- Service Task: job type, job retries
- Call Activity: process id
The most obvious place that you use an expression in a model is a BPMN Gateway, to test some property of the workflow instance variables, and take a branch depending on its value.
FEEL expressions start with an equals symbol
=, to indicate that it is a FEEL expression that should be evaluated at runtime:
=time.hour >=0 and time.hour <=12
In this example, the FEEL expression examines the
hour subkey of the
time variable. It is a boolean expression using a Boolean AND operation. If the expression returns true, then the token will flow down this branch.
Note: be careful when constructing exclusive gateways to not specify overlapping conditions. If more than one branch evaluates to true, then the token will flow down one of the true branches – but it is unpredictable which it will take.
If you construct an expression that relies on a variable subkey, an incident will be raised if the variable does not exist.
You can test the existence of the variable first using the
instance of operator:
=time instance of context and time.hour >=0 and time.hour <=12
The FEEL engine uses short-circuit evaluation – so if
time is not a context, evaluation of the expression stops.
Zeebe 0.25 will introduce the function
is defined for testing for the existence of a variable.
For a discussion on testing for null in versions of Zeebe prior to 0.25, see this GitHub issue.
You can use a FEEL expression for the Type of a Service Task:
=string(tenantId) + "-process-order"
In this example, the FEEL expression dynamically constructs the task type from the variable
FEEL includes a number of built-in functions.
string function will convert any variable value to a string value. Here we convert the
tenantId to a string, then concatenate it with
-process-order to get a unique task type.
tenantId variable in a workflow instance is set as
11011011, then the task type will be
You could use this, for example, to segment workloads.
If you want to specialize worker behavior based on the value of a variable, you can do that in the worker.
However, if you want segmented workers for QoS, or with isolated access to distinct databases, you can use a FEEL expression to get this dynamic behavior from a single process model.
Exponential back-off retries is an open feature request for the core engine.
In the meantime, here is how you can use FEEL expressions to model a back-off retry for a task.
In the “Update Retries” worker, you need to update a variable in the workflow with the following structure:
The worker code should set these values if they do not exist, and update them if they do, decrementing the
retries and appropriately setting the
timeout with the desired delay duration for the next retry (for example “P1D” for a one-day delay).
In the gateway branch leading to the “Back-off Timer”, set the Condition expression to
=retry.retries > 0.
Set the “Back-off Timer” Timer Duration to
Note: if you use this pattern multiple times in the same process, you need to isolate the state – for example by using a unique key name for the
retry key in each instance.
To use the same task type and handler code for the “Update Retries” worker, you could use custom headers to pass in the name of the key to use, and even to specify the back-off strategy to use.
The correlation key of a message catch or receive can be dynamically set.
The correlation key is the name of the variable whose value will be correlated with the message correlation key value.
You can dynamically set the correlation key based on a variable in the workflow instance.
This is similar to indirect addressing in assembly language programming.
If you set the correlation key for a message catch/receive event to
=orderType + "Id", then with the following workflow variables, the subscription will be opened like this:
To publish a message to this subscription, you would set the correlation key in the publish message request to
These are a few basic examples of using FEEL in Zeebe process models. In the next post, we’ll cover some more advanced uses.
Camunda Developer Community
Join Camunda’s global community of developers sharing code, advice, and meaningful experiences