Bruce Silver's Blog - Using Messages in Executable BPMN
Bruce Silver
Blog

Repeating Activities in BPMN

By Bruce Silver

Read Time: 6 Minutes

BPMN has a way to say an activity should be performed more than once. In fact, it has multiple ways, and students in my BPMN Method and Style training sometimes get them confused. This post will clear things up.

A Loop activity is like a Do-While loop in programming. It means perform the activity once – it could be either a task or subprocess – and then test the loop exit condition, a Boolean expression of process data. If the condition is false, perform the activity again and evaluate the condition once more. If the condition is true, exit the activity on the normal outgoing sequence flow. Repeat until the exit condition is satisfied. It’s quite handy for activities that might require multiple tries to complete successfully. It is possible to set a maximum number of allowed iterations.

The semantics of a Loop activity are exactly the same as a non-Loop activity followed by an XOR gateway that either loops back to the activity or continues on. A Loop activity is indicated in the diagram by a circular arrow at the bottom center. This takes up less space in the diagram than adding the gateway and loopback, but it hides the loop exit condition. For that reason, Method and Style asks the modeler to insert a text annotation on any Loop activity, labeled “Loop until [condition]”.

A Multi-instance (MI) activity is like a For-Each loop in programming. It means perform the activity once – again, either a task or subprocess – for each item in a list, a process data element that contains multiple items. Processing each list item is a separate instance of the activity, and the MI activity as a whole is complete only when all the item instances are complete.

A Multi-instance activity is indicated by three parallel bars at bottom center. If the bars are vertical, it means the instances are performed at the same time, in parallel. If the bars are horizontal, which you often see with human activities, it means the instances are performed sequentially. With an MI activity, Method and Style asks the modeler to insert a text annotation, “For each [item]”.

Many beginners are confused by the difference between Loop and MI-sequential activities. They are not the same!

The key points about Loop activities are:
MI-sequential is not the same:

Let’s look at a simple example of an order.

When the order is received, the process first checks whether the items are in stock. Because an order may contain multiple items, Check stock must be done independently for each order item. In the diagram we indicate this by the text annotation. Let’s say an item is either in stock or out of stock, ignoring the case where the available stock only partially satisfies the order. Since this is processing a list, it’s MI – not Loop! The number of iterations is the number of items in the order.

Normally, in Method and Style, when an activity has two possible outcomes – in stock or out of stock – we follow it with a gateway with two gates, in stock and out of stock. But remember, with an MI activity, each instance has those two outcomes, so the MI activity as a whole has more than two possible end states. In practice, it is common to follow such an MI activity with a gateway that tests whether any item is in stock, or possibly if any item is out of stock.

Here we will continue the process if some order items are in stock. Otherwise we end the process in the end state Out of stock.

Now we Collect payment, which uses the customer’s credit card on file. That could fail. Maybe the card is expired, in which case the customer is advised to enter a valid credit card number. Collect payment is thus a Loop activity. You don’t know, when you start, how many iterations are required. You keep trying it until either it succeeds or you exhaust the allowed number of attempts. Again the loop exit condition and maximum iterations are indicated by a text annotation. There is only one instance of this activity. In the end it either succeeds or fails, so we follow it with a gateway with those two gates.

Here are some common mistakes beginners make with repeating activities:

To make a Multi-instance activity executable in the Trisotech Digital Enterprise Suite, here is how you do it. From our previous example, consider the MI task Check stock.

The input is an Order, type tOrder shown below. It is a collection of Order items, each defined by a SKU, Quantity, and UnitPrice.

In a real process, each instance of Check stock would be a database lookup, but to keep it simple here we just use a script task against the process data input Stock table, a collection of items defined by SKU and QuantityAvailable. The data output In stock items is a list of Order items that are in stock.

We first need to map the data inputs to variables in the script task context using its Data Mapping attribute.

A Multi-instance activity always iterates over a collection, so we need to select it from those supplied by input data associations, here Order. We need to assign a name to the range variable or iterator, meaning one item in the collection. It can be anything we want, so here we name it OrderItem. In the Mapping section we define the variables used in the script task logic and their mappings from the input data associations and the iterator. So variable Stock table is just the input data association of that name, and we define a new variable CurrentItem mapped from the iterator OrderItem. The mapping expression of the iterated variable must be the iterator.

The script task logic is the FEEL expression

if Stock table[SKU = CurrentItem.SKU].QuantityAvailable[1] >= CurrentItem.Quantity then CurrentItem else null

For those unfamiliar with FEEL, here is how it works. Remember we are executing the script independently over each OrderItem, and collecting the results of all the instances.

Stock table[SKU=CurrentItem.SKU].QuantityAvailable

selects the row of Stock table where the SKU matches the CurrentItem.SKU, and then finds the QuantityAvailable for that row. Since SKU is a primary key, the filter selects a single row, but technically a FEEL filter always returns a list, so we need to append [1] to extract the item. Now the script says, if that QuantityAvailable is greater than or equal to the corresponding OrderItem quantity, return the CurrentItem, otherwise return null. We run this script for each OrderItem.

Now we define the data output mapping.

A script task always has a single output. We need to assign it to a variable, here In stock item. For Resulting collection, we select one of the output data associations, here the process data output In stock items. Collected variable says that each item in that collection is assigned the script task output In stock item. Thus the data output In stock items is a collection containing the original Order item if in stock or null if out of stock.

We use In stock items in the logic of the gateway Any in stock? The yes gate condition is defined by the FEEL Boolean expression:

nn count(In stock items)>0,

where nn count(list) is a Trisotech extension function equivalent to count(list[item!=null]).

When we test the logic in Service Library TryIt, we get the expected result. Order item A001 is in stock and Order item A003 is out of stock. Thus In stock items has two items, one of them null, and the process end state is “Some in stock”.

To recap, Loop and MI activities are frequently used in BPMN and they are not the same thing. Use Loop when you need to retry an activity until it succeeds. Use MI – either sequential or parallel – when you need to perform an action for each item in a list.

Follow Bruce Silver on Method & Style.

Blog Articles

Bruce Silver

View all

Business Automation Services in Fintech

Blog

By Bruce Silver

(Read Time: 7 Minutes)

Repeating Activities in BPMN

Blog

By Bruce Silver

(Read Time: 6 Minutes)

Using Messages in Executable BPMN

Blog

By Bruce Silver

(Read Time: 6 Minutes)

XML and JSON in DMN Models

Blog

By Bruce Silver

(Read Time: 7 Minutes)

BPMN: Database Operations with OData

Blog

By Bruce Silver

(Read Time: 12 Minutes)

BPMN 101: What Is a Process?

Blog

By Bruce Silver

(Read Time: 6 Minutes)

DMN: Dealing with Nothing

Blog

By Bruce Silver

(Read Time: 10 Minutes)

Calling Rest Services from DMN

Blog

By Bruce Silver

(Read Time: 7 Minutes)

BPMN Decoded: Data Flow

Blog

By Bruce Silver

(Read Time: 6 Minutes)

BPMN Basics: Providing Information to a Process

Blog

By Bruce Silver

(Read Time: 10 Minutes)

CMMN Method and Style – Part 2

Blog

By Bruce Silver

(Read Time: 8 Minutes)

CMMN Method and Style – Part 1

Blog

By Bruce Silver

(Read Time: 10 Minutes)

Modeling Virus Transmission on an Airplane

Blog

By Bruce Silver

(Read Time: 8 Minutes)

Using Decision Services

Blog

By Bruce Silver

(Read Time: 10 Minutes)

Use Contexts to Simplify Your Decision Models

Blog

By Bruce Silver

(Read Time: 9 Minutes)

Why BKMS?

Blog

By Bruce Silver

(Read Time: 11 Minutes)

Helping the Mortgage Industry Go Digital

Blog

By Bruce Silver

(Read Time: 12 Minutes)

BPMN Style Rules

Blog

By Bruce Silver

(Read Time: 6 Minutes)

DMN, Meet Machine Learning

Blog

By Bruce Silver

(Read Time: 12 Minutes)

Matrix Operations in DMN

Blog

By Bruce Silver

(Read Time: 15 Minutes)

previous arrowprevious arrow
next arrownext arrow
Slider
All Blog Articles

Read our experts’ blog

View all

Slider

Models of Regulatory Compliance

Connecting Source Documents to Process and Decision through Concept Models

Presented by:

Tom DeBevoise
Advanced Component Researche inc.

Trisotech partner, Tom DeBevoise demonstrates how to implement Regulatory Compliance using Trisotech software.

Videos

Recorded webinars

View all videos
Attend a live webinar

Slider
Bruce Silver's Blog - Using Messages in Executable BPMN
Bruce Silver
Blog

Using Messages in Executable BPMN

By Bruce Silver

Read Time: 6 Minutes

In BPMN, the most common way information is provided to a process from an external source is via a message. Incoming messages are indicated in the diagram by a dashed arrow connector called a message flow, with its tail on a black-box pool or a message node in another process pool and its arrow on a message node in the receiving process, either an activity or message event. In our BPMN Method and Style training, which focuses on non-executable processes, we discuss at length the semantics and usage patterns of messages and message events. But when we take the next step of making our BPMN model executable, we need to think about messages in a new way. This post explains how it works.

Below is a variant of an example from the training, illustrating the use of message boundary events.

The scenario is as follows:

The semantics above are inherent in the definition of message start and boundary events. One thing to note: The state of the process is unknown to the Customer when he or she sends the Cancellation message. Thus a single Cancellation message must be represented in the diagram by separate message flows leading to different message events in the process, each event triggering a different way of handling the message. In the BPMN Method and Style training, we recommend that these message flows carry identical labels and the receiving message events do as well. In executable BPMN, these recommendations become absolute requirements.

When we make a model like this one executable, we need to think about messages from a new angle. An executable process is a service, and incoming messages are really API calls from an external client. On the Trisotech platform, for example, when we click Cloud Publish in a BPMN model, the tool compiles and deploys each process in the model – there could be more than one – as a REST service accessible through the Service Library. If the only interaction with the Customer were the initial Order, we might not draw the Customer pool and message flows at all. Instead we would make Order a process data input, which is equivalent to the start message. But when we have subsequent interactions, as in this model, we should use the message flow representation, because it implies that Cancellation messages addressed to this process are meant to cancel only this particular instance – this particular order – not all instances of the process.

Maybe this has got you thinking…

  1. How do we address a message to a particular process?
  2. How do we address a message to a particular instance of the process?
  3. How does the instance know which message event receives the message?

All good questions, and we will answer them shortly.

The key difference between non-executable and executable BPMN is the latter defines process data in the form of data objects and defines mappings between process activities or events and these data objects. I have to tell you at the start that while all BPMN products generally follow the semantics defined in the spec, the implementation details of executable BPMN vary from product to product. What follows is how it works in the Trisotech Digital Enterprise Suite. I like this platform because it is designed for non-programmers, borrowing from DMN a business-friendly way of modeling and mapping data objects.

When we add the data objects to the diagram, it looks like this:

The diagram now looks cluttered and hard to read, but you can right-click and Hide the data objects, replacing them with three dots at the bottom of each activity mapped to or from the data object. The data objects with black arrows are data outputs, meaning their values are returned upon execution. In this case we simply want to capture in the output the Status of the order – “Received”, “Completed”, or “Cancelled” – and timestamps indicating precisely when the order was Received, Completed, or Cancelled, along with any Refund info. The reason we need to break these out as separate data outputs as opposed to components of a single structured output is that a data output association – that dotted arrow connector from a task or event to the data object – rewrites the entire data object; it does not simply update selected components.

So let’s see how to make this executable. We start with the datatypes, defined on the BPMN ribbon. The Order message is type tOrder, a structure that looks like this:

We assign the message flow Order to this datatype, and this associates the message flow with a message named Order, type tOrder. We do something similar to the message flows named Cancellation, using the type tCancellation.

Later we’ll see how the OrderID component of Cancellation is used to select a particular instance of the Order process.

We also assign the type tOrder to the message start event Receive order. With an incoming message, we always need to save the message payload to one or more data objects, here represented in the diagram as data associations to Order info (type tOrder) and Received, which captures the timestamp of receival. The data mapping from the start event is shown below. Received is populated with the current timestamp, using the Trisotech FEEL extension function now(), and Status is populated with the value “Received”. Order info passes order details to the other activities in the process.

Following the scenario described previously, we collect payment, fulfill the order, and complete. If a Cancellation message for this order is received while in the activity Collect payment, we set the Status to “Cancelled” and end the process in the state Order cancelled. If the Cancellation is received while in the activity Fulfill order, we again set the Status to “Cancelled”, calculate the amount to refund, and end in Order Cancelled. If Fulfill order completes with no Cancellation, we set the Status to “Completed” end in Order complete.

We model the Cancellation message flows in a similar way: Assign them and their catching boundary events to the type tCancellation and map the message content to Cancel info, Status, and Cancelled as we did with Order. For this example we ignore the details of the tasks Process payment and Fulfill order, except that completion of Fulfill order sets the Status and Completed timestamp, as shown by the output data mapping below.

Process Refund calculates the refunded amount. Here we are using simply Order info.Amount, but we made it a decision task to allow for more complex logic, such as a change in the price between time of ordering and cancellation. The data output Refund info reports the refunded amount and a timestamp.

Now we also need to provide a way to identify this particular instance of the order process. The primary method used by Trisotech is called instance tagging. At the process level you define one or more strings that uniquely identify the instance. These must be strings not structured data, so if you want to associate a value, such as the Order ID, with a label, you need to concatenate the label and the value. In the BPMN diagram, right-click Attributes/Process Instance Tags and define one or more label-value strings that identify a single process instance or possibly a small collection of instances:

Since each Order has a unique ID, this tag always identifies a single instance.

We want to tell the Receive cancellation events to accept only Cancellation messages for the current instance. Right-click the boundary event and select Message correlation. As you see below, Trisotech uses a three-stage filter for correlation, although typically one or more of the stages is not used.

The first stage, a message content filter, is a boolean expression of message data that makes no reference to the process instance. The second stage, instance tag matching, is the most common, and what we use in our example. It is a FEEL expression of type Text referencing attributes of the incoming message (here, Cancellation). Only strings matching a process instance tag are received, i.e., Cancellation messages in which the component OrderID matches Order info.ID. Because the instance tags are indexed, the runtime can do this correlation matching very quickly.

The third stage is a boolean expression of process instance data. It is very flexible but unless you have cut down the list of available messages using the first two filters, it could be slow. It should be used only in special cases.

So let’s now test our executable process. To do that, on the Execution ribbon click Cloud Publish, which compiles the logic and deploys it as a REST service accessible through the Service Library. There you see the various endpoints created for this service:

This answers the first question posed at the start of this post: How do we address a message to a particular process? It’s via the endpoint URL. In the modeling tool, my process has the name message flows5 executable, and this is version 1.0 of that process. So a POST to [base]/bpmn/api/run/test/bpmn/message-flows5-executable/1.0 is equivalent to sending the message Order to the start event. You can expand that box to see the required input data and the data returned when the process completes for various response codes:

As you can see, these are the json equivalents of the FEEL message definitions. Also note that POSTing an API call to [base]/trigger/test/bpmn/message-flows5-executable/1.0/default/Cancellation is equivalent to sending the Cancellation message to the boundary events. Here the name of both the process and the message event are part of the endpoint URL. Correlation to the particular instance of the process – this specific order – is achieved via the Process Instance Tag.

We can test execution of this process from the Service Library. The TryIt button exposes a form where you can input Order data.

Clicking Run advances the process to Process payment.

Here the Status is “Received” and the data output Received contains the timestamp of receival. The Continue service section lets you select either Process payment, meaning run this activity, or Receive cancellation, the boundary event. If we click Process payment, we see the data mapped to this task, and we can define any output data values. Clicking Run again advances to Fulfill order. Again the Continue service section lets us either run the task or receive the Cancellation message. This time let’s click Receive cancellation. We are prompted to define the Cancellation message:

Clicking Run now should exit on the exception flow, run the decision task, and end with Status “Cancelled”, end state “Order cancelled”, with a Cancellation timestamp and Refund info populated. You can see from the data outputs that it does exactly that.

The answer to the third question posed at the top – How does the instance know which event catches the message? – is simply based on timing. It can be received only by an active node at runtime.

Let’s recap. As you can see, executable BPMN is a bit more involved than normal non-executable Method and Style. Modeling real-world processes almost always involves incoming messages, which in executable BPMN are API calls to the deployed BPMN service. We model message data in the normal way, via FEEL datatypes, and use data mapping to save that data to data objects used in the process. At runtime, messages are routed to the right process and message event via the endpoint URL, and correlated to a particular instance via Process Instance Tags. We can test and debug the logic, including waiting for message events, via the Service Library. And best of all, none of this requires programming.

If this interests you – and it should! – contact Trisotech to find out how they can set you up for success.

Follow Bruce Silver on Method & Style.

Blog Articles

Bruce Silver

View all

Business Automation Services in Fintech

Blog

By Bruce Silver

(Read Time: 7 Minutes)

Repeating Activities in BPMN

Blog

By Bruce Silver

(Read Time: 6 Minutes)

Using Messages in Executable BPMN