Toggle menu

Multi-Instance Tasks

Setting a task, or complete sub-process, as multi-instance means it will be executed more than once. You are able to set the number of executions, whether they are executed sequentially or in parallel, and define a process variable that will supply information to each of the tasks repetitions.

Multi-instance behaviour can also be implemented by creating a loop around your task using a gateway to send the flow back to an earlier point until certain conditions are met. Whether you create a loop, or use the multi-instance property, is up to you.

Throughout this documentation, and the BPMN schema, the term multi-instance is used. It's important not to confuse these "instances" with an instance of a workflow process. Multi-instances of a task are actually multiple executions within an instance.

Creating a Multi-Instance Mail Task

In this example a mail task has been set as multi-instance. This means it will send multiple emails. The properties of the mail task (who each email is sent to etc) are taken from a process variable.

A Multi Instance Mail Task
 

The script task sets the following process variable, called SUBSCRIBERS. In this simple example the values are fixed. More realistically this variable would be set following an API Server task (perhaps querying site users) or take values from a form submission or other workflow process.

execution.setVariable("SUBSCRIBERS", [{
    "name": "Tim",
    "email": "tim@gossinteractive.com"
}, {
    "name": "Bill",
    "email": "bill@gossinteractive.com"
}]);

All of the properties for setting up a multi-instance task are found on the Advanced tab.

Advanced Tab Multi-Instance Properties
 

Multi-Instance Type

The multi-instance type property sets whether the instances are executed sequentially or in parallel (or at all). Sequential instances are completed one at a time, parallel instances all start at once.

Cardinality

This property sets a fixed number of times this task will execute. It is the simplest way to mark a task as multi-instance, especially if each execution of the task is identical.

Care should be taken when using cardinality in combination with a collection. For example, adding 1 in the example above would mean that only one email would be sent, even though we have two email addresses. Setting 3 would send two emails then generate an error.

Collection

The collection property is the name of, generally, a process variable that holds information for each of the instances you'd like to create. In the example above it's SUBSCRIBERS, matching the variable set in the script task. You can also use a ${...} expression that evaluates to a name.

An execution of the task will be created for every item in the collection. In the example above, two executions will be created, one for each object in the array. If the collection is an empty array, no executions will be created.

Element Variable

When an execution is created for each item in a collection, a process variable is created that accompanies each execution, holding the information from the collection relevant to it. The element variable property lets you set the name of that process variable.

In our example the process variables will be called subscribers. For the first execution it would be:

"subscribers": {  
    "name": "Tim",
    "email": "tim@gossinteractive.com"
}

and for the second:

"subscribers": {  
    "name": "Bill",
    "email": "bill@gossinteractive.com"
}

Completion Condition

This property lets you enter a ${...} expression that will be evaluated every time an execution of the multi-instance task completes. If it ever evaluates to true, all remaining executions will be destroyed and the instance execution will move on.

The Mail Task

With the multi-instance settings above, the mail task could be set up to send a customised email to all of the users in the SUBSCRIBERS collection.

The "to" property could contain the expression ${subscribers.email} (our element variable was called subscribers and we want the email property from the object).

The email body could include 

Hello ${subscribers.name}
Here's a multi-instance mail task!

Once all of the multi-instance executions have completed, the instance execution moves on, in this case to a standard end event, ending the process.

Multi-Instance User Tasks

There are a few gotchas to consider when creating multi-instance user tasks, which make them generally unsuitable for everything but the most basic activities. If you need to create a task that should be completed by multiple users, it's often best to use a multi-instance call activity.

Candidates and Ordering

Imagine you create two instances of a user task, and select two candidates for it. What would happen if you set the task as parallel? What about sequential?

Creating two sequential executions of a task and selecting two candidates does not mean the task will go first to one candidate then the other. It means one execution will be created, which either candidate can complete, then another execution will be created, which either candidate can complete.

Creating two parallel executions means that two executions will appear in the task lists of each user, and either (or both) users can complete them. As long as the task is completed twice, even twice by the same user, the execution will move on.

To create multiple tasks to be carried out by one user then another, or a selection of users in parallel, you need to create a collection of users using a script task that sets a process variable, just like the mail task example above.

This script sets the usernames:

execution.setVariable("USERS", ["Timg","Bill"]);

The user task looks for the collection called USERS and creates an element variable called user. The candidate users are then assigned using the expression ${user}. This means that each execution of the task only has a single candidate eligible to complete it. Candidate groups can be set in a similar way.

Problems with Task Forms

User tasks are completed by users submitting forms. The values of form submissions are stored as process variables. Process variables are mapped to the fields on the task form by name. Because each of the user tasks in a multi-instance situation uses the same form, you can run into problems.

Imagine the first user in our sequence of multi-instances completes a task, typing the phrase "here is my response" into the field called RESPONSE. When the second user comes to complete the task, they will see the response of the first user in the response field, and there won't be any space for them to type anything new.

This is one of the limitations of multi-instance user tasks. They, by definition, present instances of the same task (and the same form, and therefore any process variables) to each user. This can be useful if all the user needs to do is approve some content, perhaps by submitting the form.

Ongoing Sequence Flow

Consider this workflow with a multi-instance user task.

A Multi-Instance User Task
 

Immediately after the task is an exclusive gateway, which will send the execution down either the "Yes" or "No" branch, depending upon the choice made in the user task.

However, the user task is multi-instance, so how does the flow know which branch to take?

It vital to remember that a multi-instance task doesn't create an ongoing execution as each task is completed. The execution waits at the user task until all of the defined instances are completed, then a single execution proceeds. In this example the flow condition is determined by evaluating a single process variable, either ${form_RADIOGROUP=="Yes"} or ${form_RADIOGROUP=="No"}. When all of the user task instances have completed, whatever the value of that variable is will determine the flow - which in practice means the last user to complete the task gets to decide.

Last modified on 18 October 2019

Share this page

Facebook icon Twitter icon email icon

Print

print icon