Skip to Content
Flower 3.7.0 is released 🎉 See what's new
DocsGuidesDecide with Gateways
Guides· 5 min read· Updated November 2026

BPMN Gateways & Decision Handling

A gateway lets a process choose between several paths. At an XOR gateway, Flower makes the choice automatically: every outgoing transition has a condition, and the process follows the first one that is true.

📖

Reference: BPMN Gateways explains exclusive, parallel, and inclusive gateways in the BPMN standard and when to use which.

This guide explains how these decisions work, how to write expressions with the data of your Jira work items, and how to keep your process moving when data is missing.

Flower takes the first outgoing flow whose expression is true; the default flow keeps the process moving when none is.

How Gateway Decisions Work

When a process reaches an XOR gateway, the Flower engine evaluates the expressions that are stored on the outgoing transitions of the gateway. The process follows the first transition whose expression is true.

An expression is a condition in a JavaScript-like syntax inside ${ }: fields, comparisons, &&, ||, !, arithmetic, and a few text and list methods such as includes or startsWith (the complete list is in What an Expression Can Do; functions such as Date or filter are not allowed). Flower evaluates it with the data of your Jira work items, for example ${cur.fields.status.name == 'Rejected'}. If you leave out the braces, Flower adds them.

Expressions on the outgoing transitions of an XOR gateway

ℹ️

If a transition loops back to an activity that is already completed, Flower reopens its work item.
For this, the workflow must offer a transition without a screen from the completed status back to a To Do or In Progress status. Otherwise, Flower cannot reopen the work item and adds an error comment to the process instance.

Write Expressions

An expression checks a value of a work item and returns true or false. Always write the whole expression inside ${ }. For example, ${pi.fields.summary} returns the summary of the process instance.

Choose the Right Work Item

Three work items are available in an expression:

NameWork itemTypical use
curThe current work item: the work item whose resolution moved the process to the gateway, usually the work item of the task before itCheck the outcome of the last task, for example whether it was resolved, approved, or rejected
piThe process instance work itemCheck data from the start of the process that stays the same, such as fields of the process form
parThe parent: the process instance that called this process as a sub-processRead data of the calling process inside a sub-process, for example ${par.fields.summary == 'New Request'}. In a process that is not a sub-process, par is empty

All three give you the work item as the Jira REST API returns it: fields contain the fields, properties contain the work item properties. For pi and cur, the fields are also available directly: pi.summary is the same as pi.fields.summary. For par, always write fields. In a few situations cur is another work item, for example after a parallel join or a timer; the complete rules are in Expressions.

Example Expressions

#ExpressionWhat it checks
1${pi.fields.summary == 'New Request'}The summary of the process instance is New Request
2${cur.fields.status.name == 'Rejected'}The last work item has the status Rejected
3${cur.fields.resolution.name == 'Done'}The last work item was resolved as Done
4${cur.fields.priority.name == 'Low'}The last work item has the priority Low
5${cur.fields.assignee.accountId == '557058:fp60faa5-xxxx-4344-yyyy-4becd42z7914'}The last work item is assigned to this user
6${cur.fields.customfield_10113 >= 5000}A number field of the last work item is at least 5000
7${cur.fields.customfield_10115.value == 'yes'}A select field of the last work item has the value yes
8${pi.properties.flowerVariables.external.data.value >= 1000}External data stored on the process instance is at least 1000
9${pi.fields.comment.comments[0].author.accountId == '557058:fp60faa5-xxxx-4344-yyyy-4becd42z7914'}The first comment on the process instance was written by this user
10${pi.fields.customfield_10023.requestType.name == 'Technical support'}The request type of the process instance is Technical support (service space)

With such conditions, only the relevant transition is taken. This reduces manual input and automates decisions.

Complex Fields and External Data

Many fields, especially custom fields, are objects: a select field has its text in .value, a user in .accountId, a request type in .requestType.name. How to find the structure of a field, and how to bring data from outside Jira into a decision (flowerVariables), is described in the reference Expressions.

Default Transitions: Ensuring the Process Keeps Moving

A default transition is the path that the process takes when no other condition is true, also when a condition is false because of a missing field. Without it, the process stops at the gateway with an error comment, see Exclusive Gateways. Default transitions are especially useful when a decision depends on dynamic data, such as a custom field.

An approval process with an XOR gateway: the sequence flow is changed to the default flow in the context menu, highlighted in red

In the Capital Investment Approval Process, an XOR gateway decides based on the custom field approval:

  • YES → CFO/Board Approval → Investment Execution
  • NO (default) → Rework Request → Resubmit Investment Request
  • REJECT → Investment Rejected → End Process

Why Use a Default Path?

If a condition fails, for example because a field value is missing or wrong, the process does not break. It follows the default path, and the requester can review, refine, and resubmit the investment request. Flower also writes a comment on the process instance that explains the failure, see Troubleshooting Expressions.

With a default path, your process stays robust, even if data in Jira is missing or inconsistent.

Troubleshooting Expressions

Flower can only check an expression at runtime, because only then the full execution context is available.

Keep these rules in mind:

RuleExample
Put the whole condition inside one ${ }${cur.fields.status.name == 'Rejected'} is a condition. In ${cur.fields.status.name} == 'Rejected', only the part in the braces is evaluated, and the result is text instead of true or false.
Expressions are case-sensitiveSummary is not summary
Compare types carefully'123' === 123 is false, because a string is not a number. The operator == converts types, so do not rely on it for strings and numbers.
Many fields store data in nested propertiesA custom field often needs .value or .name, for example ${cur.fields.customfield_10115.value == 'yes'}

If an expression refers to a field that does not exist, the condition is false and Flower writes a comment on the process instance, once per process instance for each gateway and expression. A field that exists but is empty makes the condition false without a comment. The details are in Expressions.

Example: Expression validation failed

❌ Expression validation failed at: bpmn:ExclusiveGateway[Gateway_10td181] Expression: ${cur.fields.summary.value == 'a'} Error: Missing field 'value' at path 'cur.fields.summary.value' Context: pi: FLOW-106 cur: FLOW-107 model: FLOW-47 🔍 Tip: Use the Jira REST API to inspect your work item data: → /rest/api/latest/issue/FLOW-107 📘 Docs: https://flower-bpm.com/docs/concepts/gateway-decision-handling

In Jira Data Center, Flower also writes the evaluation to its log file, see Flower for Jira Data Center.

Test your expressions with real work item data, especially for custom fields and advanced structures such as work item links or SLA objects. You can inspect a work item in the Jira REST API .

What’s Next?

Last updated on