BPMN 2.0 Implementation Reference

BPMN 2.0 Overview and Coverage

This page gives you an overview of the BPMN 2.0 elements and the current coverage of the process engine.

Heads up! If you are unfamiliar with BPMN 2.0 you might want to check out our BPMN Tutorial first.

The elements marked in orange are supported. Hover over the element to see since which version of the camunda BPM platform they are supported.

Participants

Subprocesses

Gateways

Data

Artifacts

Events

In BPMN there are Start events, Intermediate events, and End events. These three event types can be catching events and/or throwing events. Intermediate events can be used as boundary events on tasks, in which case they can be interrupting or non-interrupting. This gives you a lot of flexibility to use events in your processes.

Heads up! For understanding the principle behavior of events in BPMN, we recommend to check the Events: Basic Concepts chapter of the BPMN Modeling Reference section.
Type Start Intermediate End
Normal Event Subprocess Event Subprocess
non-interrupt
catch boundary boundary
non-interrupt
throw
None
Message
Timer
Conditional
Link
Signal
Error
Escalation
Termination
Compensation
Cancel
Multiple
Multiple Parallel

Service Task

A service task is used to invoke services. In camunda this is done by calling Java code.

There are 4 ways of declaring how to invoke Java logic:

  • Specifying a class that implements JavaDelegate or ActivityBehavior
  • Evaluating an expression that resolves to a delegation object
  • Invoking a method expression
  • Evaluating a value expression

To specify a class that is called during process execution, the fully qualified classname needs to be provided by the camunda:class attribute.

<serviceTask id="javaService"
             name="My Java Service Task"
             camunda:class="org.camunda.bpm.MyJavaDelegate" />

Please refer to the Java Delegate section of the User Guide for details on how to implement a Java Delegate.

It is also possible to use an expression that resolves to an object. This object must follow the same rules as objects that are created when the camunda:class attribute is used.

<serviceTask id="beanService"
             name="My Bean Service Task"
             camunda:delegateExpression="${myDelegateBean}" />

Or an expression which calls a method or resolves to a value.

<serviceTask id="expressionService"
             name="My Expression Service Task"
             camunda:expression="${myBean.doWork()}" />

For more information about expression language as delegation code please see the corresponding section of the User Guide.

Generic Java Delegates & Field Injection

You can easily write generic Java Delegate classes which can be configured later on via the BPMN 2.0 XML in the Service Task. Please refer to the Field Injection section of the User Guide for details.

Service task results

The return value of a service execution (for a service task exclusively using expression) can be assigned to an already existing or to a new process variable by specifying the process variable name as a literal value for the camunda:resultVariable attribute of a service task definition. Any existing value for a specific process variable will be overwritten by the result value of the service execution. When not specifying a result variable name, the service execution result value is ignored.

<serviceTask id="aMethodExpressionServiceTask"
           camunda:expression="#{myService.doSomething()}"
           camunda:resultVariable="myVar" />

In the example above, the result of the service execution (the return value of the doSomething() method invocation on object myService) is set to the process variable named myVar after the service execution completes.

Result variables and multi-instance

Note that when you use camunda:resultVariable in a multi-instance construct, for example in a multi-instance subprocess, the result variable is overwritten every time the task completes, which may appear as random behavior. See camunda:resultVariable for details.

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:class, camunda:delegateExpression, camunda:exclusive, camunda:expression, camunda:resultVariable, camunda:type
Extension Elements camunda:failedJobRetryTimeCycle, camunda:field, camunda:connector, camunda:inputOutput
Constraints One of the attributes camunda:class, camunda:delegateExpression, camunda:type or camunda:expression is mandatory
The attribute camunda:resultVariable can only be used in combination with the camunda:expression attribute
The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Send Task

A send task is used to send a message. In camunda this is done by calling Java code.

The send task has the same behavior as a service task.

<sendTask id="sendTask" camunda:class="org.camunda.bpm.MySendTaskDelegate" />

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:class, camunda:delegateExpression, camunda:exclusive, camunda:expression, camunda:resultVariable, camunda:type
Extension Elements camunda:failedJobRetryTimeCycle, camunda:field, camunda:connector, camunda:inputOutput
Constraints One of the attributes camunda:class, camunda:delegateExpression, camunda:type or camunda:expression is mandatory
The attribute camunda:resultVariable can only be used in combination with the camunda:expression attribute
The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

User Task

A user task is used to model work that needs to be done by a human actor. When the process execution arrives at such a user task, a new task is created in the task list of the user(s) or group(s) assigned to that task.

A user task is defined in XML as follows. The id attribute is required while the name attribute is optional.

<userTask id="theTask" name="Important task" />

Description

A user task can have also a description. In fact, any BPMN 2.0 element can have a description. A description is defined by adding the documentation element.

<userTask id="theTask" name="Schedule meeting" >
  <documentation>
      Schedule an engineering meeting for next week with the new hire.
  </documentation>

The description text can be retrieved from the task in the standard Java way:

task.getDescription();

Due Date

Each task has a field indicating the due date of that task. The Query API can be used to query for tasks that are due on, before or after a certain date.

There is an activity extension which allows you to specify an expression in your task-definition to set the initial due date of a task when it is created. The expression should always resolve to a java.util.Date, java.util.String (ISO8601 formatted) or null. When using ISO8601 formatted Strings, you may either specify an exact point in time or a time period relative to the time the task is created. For example, you could use a date that was entered in a previous form in the process or calculated in a previous Service Task.

<userTask id="theTask" name="Important task" camunda:dueDate="${dateVariable}"/>

The due date of a task can also be altered using the TaskService or in TaskListeners using the passed DelegateTask.

Follow Up Date

Each task has a field indicating the follow up date of that task. The Query API can be used to query for tasks that need to be followed up on, before or after a certain date.

There is an activity extension which allows you to specify an expression in your task-definition to set the initial follow up date of a task when it is created. The expression should always resolve to a java.util.Date, java.util.String (ISO8601 formatted) or null. When using ISO8601 formatted Strings, you may either specify an exact point in time or a time period relative to the time the task is created. For example, you could use a date that was entered in a previous form in the process or calculated in a previous Service Task.

<userTask id="theTask" name="Important task" camunda:followUpDate="${dateVariable}"/>

User Assignment

A user task can be directly assigned to a user. This is done by defining a humanPerformer sub element. Such a humanPerformer definition needs a resourceAssignmentExpression that actually defines the user. Currently, only formalExpressions are supported.

<process ... >
  ...
  <userTask id='theTask' name='important task' >
    <humanPerformer>
      <resourceAssignmentExpression>
        <formalExpression>kermit</formalExpression>
      </resourceAssignmentExpression>
    </humanPerformer>
  </userTask>

Only one user can be assigned to the task as a human performer. In the engine terminology, this user is called the assignee. Tasks that have an assignee are not visible in the task lists of other users and can be found in the so-called personal task list of the assignee instead.

Tasks directly assigned to users can be retrieved through the TaskService as follows:

List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();

Tasks can also be put in the so-called candidate task list of people. In that case, the potentialOwner construct must be used. The usage is similar to the humanPerformer construct. Please note that for each element in the formal expression it is required to specifically define if it is a user or a group (the engine cannot guess this).

<process ... >
  ...
  <userTask id='theTask' name='important task' >
    <potentialOwner>
      <resourceAssignmentExpression>
        <formalExpression>user(kermit), group(management)</formalExpression>
      </resourceAssignmentExpression>
    </potentialOwner>
  </userTask>

Tasks defined with the potential owner construct can be retrieved as follows (or a similar TaskQuery, such as for tasks which have an assignee, can be used):

List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");

This will retrieve all tasks where kermit is a candidate user, i.e. the formal expression contains the user kermit. This will also retrieve all tasks that are assigned to a group of which kermit is a member (e.g. group(management), if kermit is a member of that group and the identity component is used). The groups of a user are resolved at runtime and these can be managed through the IdentityService.

If no specifics are given whether the given text string is a user or a group, the engine defaults to group. So the following two alternatives lead to the same result:

<formalExpression>accountancy</formalExpression>
<formalExpression>group(accountancy)</formalExpression>

User Assignment using custom extensions

It is clear that user and group assignments are quite cumbersome for use cases where the assignment is more complicated. To avoid these complexities, custom extensions on the user task are possible.

  • assignee attribute: this custom extension allows direct assignment of a user task to a given user.

    <userTask id="theTask" name="my task" camunda:assignee="kermit" />

    This is exactly the same as using a humanPerformer construct as defined above.

  • candidateUsers attribute: this custom extension allows you to make a user a candidate for a task.

    <userTask id="theTask" name="my task" camunda:candidateUsers="kermit, gonzo" />

    This is exactly the same as using a potentialOwner construct as defined above. Note that it is not required to use the user(kermit) declaration as is the case with the potential owner construct, since this attribute can only be used for users.

  • candidateGroups attribute: this custom extension allows you to make a group a candidate for a task.

    <userTask id="theTask" name="my task" camunda:candidateGroups="management, accountancy" />

    This is exactly the same as using a potentialOwner construct as defined above. Note that it is not required to use the group(management) declaration as is the case with the potential owner construct, since this attribute can only be used for groups.

  • candidateUsers and candidateGroups can both be defined for the same user task.

Note: Although the camunda engine provides an identity management component, which is exposed through the IdentityService, it does not check whether a provided user is known by the identity component. This allows integration of the engine with existing identity management solutions when it is embedded into an application.

In case the previous approaches are not sufficient, it is possible to delegate to custom assignment logic using a task listener on the create event:

<userTask id="task1" name="My task" >
  <extensionElements>
    <camunda:taskListener event="create" class="org.camunda.bpm.MyAssignmentHandler" />
  </extensionElements>
</userTask>

The DelegateTask that is passed to the TaskListener implementation, allows you to set the assignee and candidate-users/groups:

public class MyAssignmentHandler implements TaskListener {
  public void notify(DelegateTask delegateTask) {
    // Execute custom identity lookups here
    // and then for example call following methods:
    delegateTask.setAssignee("kermit");
    delegateTask.addCandidateUser("fozzie");
    delegateTask.addCandidateGroup("management");
    ...
  }
}

When using Spring or CDI it is possible to use the custom assignment attributes as described in the section above and delegate to a bean using a task listener with an expression that listens to task create events. In the following example, the assignee will be set by calling the findManagerOfEmployee on the ldapService Spring/CDI bean. The emp parameter that is passed is a process variable>.

<userTask id="task" name="My Task" camunda:assignee="${ldapService.findManagerForEmployee(emp)}"/>

This also works in a similar way for candidate users and groups:

<userTask id="task" name="My Task" camunda:candidateUsers="${ldapService.findAllSales()}"/>

Note that this will only work if the return type of the invoked methods is String or Collection (for candidate users and groups):

public class FakeLdapService {

  public String findManagerForEmployee(String employee) {
    return "Kermit The Frog";
  }

  public List<String> findAllSales() {
    return Arrays.asList("kermit", "gonzo", "fozzie");
  }
}

Forms

It is possible to provide information to render a user task form by using the camunda:formKey attribute:

<userTask id="someTask" camunda:formKey="someForm.html">
  ...
</userTask>

The form key is a symbolic value which can be set in the BPMN XML file by using the extension attribute formKey and retrieved at runtime using the process engine API.

If the user task form is displayed inside the Camunda Tasklist, the format of the formKey must follow special rules. See the corresponding section in the user guide for details.

In custom applications, the value of the form key can be chosen freely. In a custom application the value of the form key attribute can be interpreted freely. Based on the specific UI technology used, it can reference the name of an HTML file, a JSF / Facelets template, a Vaadin / GWT view, ...

Retrieving the form key using the form service.

String formKey = formService.getTaskFormData(someTaskId).getFormKey();

Retrieving the form using the task service

When performing a task query, it is possible to retrieve the form key as well. This is most useful if the form keys need to be retrieved for a complete list of tasks:

List<Task> tasks = TaskService.createTaskQuery()
  .assignee("jonny")
  .initializeFormKeys() // must be invoked
  .list();

for(Task task : tasks) {
  String formKey = task.getFormKey();
}

Note that it is required to call the .initializeFormKeys() method on the TaskQuery object to make sure the form keys are initialized.

camunda Extensions

Attributes camunda:assignee, camunda:asyncBefore, camunda:asyncAfter, camunda:candidateGroups, camunda:candidateUsers, camunda:dueDate, camunda:exclusive, camunda:formHandlerClass, camunda:formKey, camunda:priority
Extension Elements camunda:formData, camunda:formProperty, camunda:taskListener, camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The attribute camunda:assignee cannot be used simultaneously with the humanPerformer element
Only one camunda:formData extension element is allowed
The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Business Rule Task

A Business Rule task is used to synchronously execute one or more rules.

You can use the rule engine of your choice, on the open source side we have made good experiences with JBoss Drools. To do so, you have to plug in your implementation of the rule task the same way as in a Service Task. So the only difference is that it has a different icon in the BPMN process model - but this can make already a huge difference for acceptance of the process model.

<businessRuleTask id="businessRuleTask" camunda:delegateExpression="${MyRuleServiceDelegate}" />

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:class, camunda:delegateExpression, camunda:exclusive, camunda:expression, camunda:resultVariable, camunda:type
Extension Elements camunda:failedJobRetryTimeCycle, camunda:field, camunda:connector, camunda:inputOutput
Constraints One of the attributes camunda:class, camunda:delegateExpression, camunda:type or camunda:expression is mandatory
The attribute camunda:resultVariable can only be used in combination with the camunda:expression attribute
The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Script Task

A script task is an automated activity. When a process execution arrives at the script task, the corresponding script is executed.

A script task is defined by specifying the script and the scriptFormat.

<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
  <script>
    sum = 0
    for ( i in inputArray ) {
      sum += i
    }
  </script>
</scriptTask>

The value of the scriptFormat attribute must be a name that is compatible with JSR-223 (Scripting for the Java Platform). If you want to use a (JSR-223 compatible) scripting engine, you need to to add the corresponding jar to the classpath and use the appropriate name.

The script source code has to be added as the text content of the script child element. Alternatively, the source code can be specified as an expression or external resource. For more information on the possible ways of providing the script source code please see the corresponding section of the User Guide.

For general information about scripting in the process engine, please see the Scripting section of the User Guide.

Supported Script Languages:

camunda BPM should work with most of the JSR-223 compatible script engine implementations. We test integration for Groovy, JavaScript, JRuby and Jython. See the Third Party Dependencies section of the User Guide for more details.

Variables in scripts

All process variables that are accessible through the execution that arrives in the script task can be used within the script. In the example below, the script variable inputArray is in fact a process variable (an array of integers).

<script>
    sum = 0
    for ( i in inputArray ) {
      sum += i
    }
</script>

It's also possible to set process variables in a script. Variables can be set by using the setVariable(...) methods provided by the VariableScope interface:

<script>
    sum = 0
    for ( i in inputArray ) {
      sum += i
    }
    execution.setVariable("sum", sum);
</script>

Enabling auto-storing of script variables

By setting the propery autoStoreScriptVariables to true in the process engine configuration, the process engine will automatically store all global script variables as process variables. This was the default behavior in camunda BPM 7.0 and 7.1 but it only reliably works for the Groovy scripting language (see the Set autoStoreScriptVariables section of the Migration Guide for more information).

In order to use this feature, you have to

  • set autoStoreScriptVariables to true in the process engine configuration,
  • prefix all script variables that should not be stored as script variables using the def keyword: def sum = 0. In this case the variable sum will not be stored as process variable.
Groovy-Support only:

The configuration flag autoStoreScriptVariables is only supported for Groovy Script Tasks.

Note: the following names are reserved and cannot be used as variable names: out, out:print, lang:import, context, elcontext.

Script results

The return value of a script task can be assigned to a previously existing or to a new process variable by specifying the process variable name as a literal value for the camunda:resultVariable attribute of a script task definition. Any existing value for a specific process variable will be overwritten by the result value of the script execution. When a result variable name is not specified, the script result value gets ignored.

<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" camunda:resultVariable="myVar">
  <script>#{echo}</script>
</scriptTask>

In the above example, the result of the script execution (the value of the resolved expression #{echo}) is set to the process variable named myVar after the script completes.

Result variables and multi-instance

Note that when you use camunda:resultVariable in a multi-instance construct, for example in a multi-instance subprocess, the result variable is overwritten every time the task completes, which may appear as random behavior. See camunda:resultVariable for details.

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive, camunda:resultVariable, camunda:resource
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Receive Task

A Receive Task is a simple task that waits for the arrival of a certain message. When the process execution arrives at a Receive Task, the process state is committed to the persistence storage. This means that the process will stay in this wait state until a specific message is received by the engine, which triggers the continuation of the process beyond the Receive Task.

A Receive Task with a message reference can be triggered like an ordinary event:

<definitions ...>
  <message id="newInvoice" name="newInvoiceMessage"/>
  <process ...>
    <receiveTask id="waitState" name="wait" messageRef="newInvoice">
  ...
ProcessInstance pi = runtimeService.startProcessInstanceByKey("processWaitingInReceiveTask");
EventSubscription subscription = runtimeService.createEventSubscriptionQuery()
  .processInstanceId(pi.getId()).eventType("message").singleResult();

// correlate the message
runtimeService.correlateMessage(subscription.getEventName());
// or receive the event
runtimeService.messageEventReceived(subscription.getEventName(), subscription.getExecutionId());
Correlation of a parallel multi instance isn't possible because the subscription can't be identified unambiguously.

To continue a process instance that is currently waiting at a Receive Task without a message reference, the runtimeService.signal(executionId) can be called, using the id of the execution that arrived in the Receive Task.

<receiveTask id="waitState" name="wait" />

The following code snippet shows how this works in practice:

ProcessInstance pi = runtimeService.startProcessInstanceByKey("receiveTask");
Execution execution = runtimeService.createExecutionQuery()
  .processInstanceId(pi.getId()).activityId("waitState").singleResult();

runtimeService.signal(execution.getId());

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Manual Task

A Manual Task defines a task that is external to the BPM engine. It is used to model work that is done by somebody who the engine does not need to know of and is there no known system or UI interface. For the engine, a manual task is handled as a pass-through activity, automatically continuing the process at the moment the process execution arrives at it.

<manualTask id="myManualTask" name="Manual Task" />

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Task Markers

In addition to those various types of tasks, we can mark tasks as loops, multiple instances, or compensations. Markers can be combined with task types.

Multiple Instance

A multi-instance activity is a way of defining repetition for a certain step in a business process. In programming concepts, a multi-instance matches the for each construct: it allows execution of a certain step or even a complete subprocess for each item in a given collection, sequentially or in parallel.

A multi-instance is a regular activity that has extra properties defined (so-called multi-instance characteristics) which will cause the activity to be executed multiple times at runtime. Following activities can become a multi-instance activity:

  • Service Task
  • Send Task
  • User Task
  • Business Rule Task
  • Script Task
  • Receive Task
  • Manual Task
  • (Embedded) Sub-Process
  • Call Activity
  • Transaction Subprocess

A Gateway or Event can not become multi-instance.

If an activity is multi-instance, this is indicated by three short lines at the bottom of that activity. Three vertical lines indicates that the instances will be executed in parallel, while three horizontal lines indicate sequential execution.

As required by the spec, each parent execution of the created executions for each instance will have following variables:

  • nrOfInstances: the total number of instances
  • nrOfActiveInstances: the number of currently active, i.e. not yet finished, instances. For a sequential multi-instance, this will always be 1
  • nrOfCompletedInstances: the number of already completed instances

These values can be retrieved by calling the execution.getVariable(x) method.

Additionally, each of the created executions will have an execution-local variable (i.e. not visible for the other executions, and not stored on process instance level) :

  • loopCounter: indicates the index in the for each loop of that particular instance

To make an activity multi-instance, the activity xml element must have a multiInstanceLoopCharacteristics child element.

<multiInstanceLoopCharacteristics isSequential="false|true">
 ...
</multiInstanceLoopCharacteristics>

The isSequential attribute indicates if the instances of that activity are executed sequentially or parallel.

The number of instances are calculated once, when entering the activity. There are a few ways of configuring this. On way is directly specifying a number by using the loopCardinality child element.

<multiInstanceLoopCharacteristics isSequential="false|true">
  <loopCardinality>5</loopCardinality>
</multiInstanceLoopCharacteristics>

Expressions that resolve to a positive number are also possible:

<multiInstanceLoopCharacteristics isSequential="false|true">
  <loopCardinality>${nrOfOrders-nrOfCancellations}</loopCardinality>
</multiInstanceLoopCharacteristics>

Another way to define the number of instances is to specify the name of a process variable which is a collection using the loopDataInputRef child element. For each item in the collection, an instance will be created. Optionally, it is possible to set that specific item of the collection for the instance using the inputDataItem child element. This is shown in the following XML example:

<userTask id="miTasks" name="My Task ${loopCounter}" camunda:assignee="${assignee}">
  <multiInstanceLoopCharacteristics isSequential="false">
    <loopDataInputRef>assigneeList</loopDataInputRef>
    <inputDataItem name="assignee" />
  </multiInstanceLoopCharacteristics>
</userTask>

Suppose the variable assigneeList contains the values [kermit, gonzo, foziee]. In the snippet above, three user tasks will be created in parallel. Each of the executions will have a process variable named assignee containing one value of the collection, which is used to assign the user task in this example.

The downside of the loopDataInputRef and inputDataItem is that 1) the names are pretty hard to remember and 2) due to the BPMN 2.0 schema restrictions they can't contain expressions. We solve this by offering the collection and elementVariable attributes on the multiInstanceCharacteristics:

<userTask id="miTasks" name="My Task" camunda:assignee="${assignee}">
  <multiInstanceLoopCharacteristics isSequential="true"
     camunda:collection="${myService.resolveUsersForTask()}" camunda:elementVariable="assignee" >
  </multiInstanceLoopCharacteristics>
</userTask>

A multi-instance activity ends when all instances are finished. However, it is possible to specify an expression that is evaluated every time one instance ends. When this expression evaluates to true, all remaining instances are destroyed and the multi-instance activity ends, continuing the process. Such an expression must be defined in the completionCondition child element.

<userTask id="miTasks" name="My Task" camunda:assignee="${assignee}">
  <multiInstanceLoopCharacteristics isSequential="false"
     camunda:collection="assigneeList" camunda:elementVariable="assignee" >
    <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.6 }</completionCondition>
  </multiInstanceLoopCharacteristics>
</userTask>

In this example, parallel instances will be created for each element of the assigneeList collection. However, when 60% of the tasks are completed, the other tasks are deleted and the process continues.

camunda Extensions

Attributes camunda:collection, camunda:elementVariable
Extension Elements
Constraints

Boundary events and multi-instance

Since a multi-instance is a regular activity, it is possible to define a boundary event on its boundary. In case of an interrupting boundary event, when the event is caught, all instances that are still active will be destroyed. For example, take the following multi-instance subprocess:

Here all instances of the subprocess will be destroyed when the timer fires, regardless of how many instances there are or which inner activities are currently not completed yet.

Loops

The loop marker is not natively supported yet by the engine. For Multiple Instance the number of repetitions is known in advance - which makes it a bad candidate for loops (anyway - as it defines a completion condition that may already be sufficient in some cases).

To get around this limitation the solution is to explicitly model the loop in your BPMN process:

Be assured that we have the loop marker in our backlog to be added to the engine.

Compensation

If an activity is used for compensating the effects of another activity it can be declared to be a compensation handler. Compensation handlers are not contained in the regular flow and are only executed when a compensation event is thrown.

Notice the compensation handler icon in the bottom center area of the "cancel hotel reservation" service task.

Compensation handlers may not have incoming or outgoing sequence flows.

A compensation handler must be associated with a compensation boundary event using a directed association.

In order to declare an activity to be a compensation handler, we need to set the attribute isForCompensation to true:

<serviceTask id="undoBookHotel" isForCompensation="true" camunda:class="..." />

Additional Resources

Data-based Exclusive Gateway (XOR)

An exclusive gateway (also called the XOR gateway or, in more technical terms, the exclusive data-based gateway), is used to model a decision in the process. When the execution arrives at this gateway, all outgoing sequence flows are evaluated in the order in which they have been defined. The sequence flow which condition evaluates to 'true' (or which doesn't have a condition set, conceptually having a 'true' value defined on the sequence flow) is selected for continuing the process.

Note that only one sequence flow is selected when using the exclusive gateway. In case multiple sequence flow have a condition that evaluates to 'true', the first one defined in the XML (and only that one!) is selected for continuing the process.

If no sequence flow can be selected (no condition evaluates to 'true') this will result in a runtime exception unless you have a default flow defined. One default flow can be set on the gateway itself in case no other condition matches - like an 'else' in programming languages.

Note that a gateway without an icon inside it defaults to an exclusive gateway, even if we recommend to use the X within the gateway if your BPMN tool gives you that option.

The XML representation of an exclusive gateway is straightforward: one line defining the gateway and condition expressions defined on the outgoing sequence flow. The default flow (optional) is set as attribute on the gateway itself. Note that the name of the flow (used in the diagram, meant for the human being) might be different than the formal expression (used in the engine).

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow4" />

<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="theTask1" name="${x==1}">
  <conditionExpression xsi:type="tFormalExpression">${x == 1}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="theTask2" name="${x==2}">
  <conditionExpression xsi:type="tFormalExpression">${x == 2}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3" name="else">
</sequenceFlow>

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:executionListener
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Conditional and Default Sequence Flows

A sequence flow is the connector between two elements of a process. After an element is visited during process execution, all outgoing sequence flows will be followed. This means that the default nature of BPMN 2.0 is to be parallel: two outgoing sequence flows will create two separate, parallel paths of execution.

camunda Extensions

Attributes
Extension Elements camunda:executionListener
Constraints

Conditional Sequence Flow

A sequence flow can have a condition defined on it. When a BPMN 2.0 activity is left, the default behavior is to evaluate the conditions on the outgoing sequence flow. When a condition evaluates to 'true', that outgoing sequence flow is selected. When multiple sequence flow are selected that way, multiple executions will be generated and the process will be continued in a parallel way. Note: This is different for gateways. Gateways will handle sequence flow with conditions in specific ways, depending on the gateway type.

A conditional sequence flow is represented in XML as a regular sequence flow, containing a conditionExpression sub-element. Note that at the moment only tFormalExpressions are supported. Omitting the xsi:type="" definition will simply default to this type of expression.

<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask">
  <conditionExpression xsi:type="tFormalExpression">
    <![CDATA[${order.price > 100 && order.price < 250}]]>
  </conditionExpression>
</sequenceFlow>

Currently conditionalExpressions can be used with UEL and scripts. The expression or script used should resolve to a boolean value, otherwise an exception is thrown while evaluating the condition.

The example below references data of a process variable, in the typical JavaBean style through getters.

<conditionExpression xsi:type="tFormalExpression">
  <![CDATA[${order.price > 100 && order.price < 250}]]>
</conditionExpression>

This example invokes a method that resolves to a boolean value.

<conditionExpression xsi:type="tFormalExpression">
  <![CDATA[${order.isStandardOrder()}]]>
</conditionExpression>

In this example a simple groovy script is used to evaluate a process variable status.

<conditionExpression xsi:type="tFormalExpression" language="groovy">
  <![CDATA[status == 'complete']]>
</conditionExpression>

Similar to a script task also an external script resource can be specified (see documentation on script source for more information).

<conditionExpression xsi:type="tFormalExpression" language="groovy"
  camunda:resource="org/camunda/bpm/exampe/condition.groovy" />

camunda Extensions for conditionExpression

Attributes camunda:resource
Extension Elements
Constraints

Default Sequence Flow

All BPMN 2.0 tasks and gateways can have a default sequence flow. This sequence flow is only selected as the outgoing sequence flow for that activity if and only if none of the other sequence flows could be selected. Conditions on a default sequence flow are always ignored.

A default sequence flow for a certain activity is defined by the default attribute on that activity. The following example shows an exclusive gateway with a default sequence flow. Only when x is neither 1 nor 2 it will be selected as outgoing sequence flow for the gateway.

Note the 'slash' marker at the beginning of the default sequence flow. The corresponding XML snippet shows how flow4 is configured as a default sequence flow.

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow4" />

<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="theTask1" name="${x==1}">
  <conditionExpression xsi:type="tFormalExpression">${x == 1}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="theTask2" name="${x==2}">
  <conditionExpression xsi:type="tFormalExpression">${x == 2}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3" name="else">
</sequenceFlow>

Parallel Gateway

Gateways can also be used to model concurrency in a process. The most straightforward gateway to introduce concurrency in a process model is the Parallel Gateway, which allows forking into multiple paths of execution or joining multiple incoming paths of execution.

The functionality of the parallel gateway is based on the incoming and outgoing sequence flow(s):

  • fork: all outgoing sequence flows are followed in parallel, creating one concurrent execution for each sequence flow.
  • join: all concurrent executions arriving at the parallel gateway wait at the gateway until an execution has arrived for each of the incoming sequence flows. Then the process continues past the joining gateway.

Note that a parallel gateway can have both fork and join behaviors, if there are multiple incoming and outgoing sequence flows for the same parallel gateway. In that case, the gateway will first join all incoming sequence flows, before splitting into multiple concurrent paths of executions.

An important difference with other gateway types is that the parallel gateway does not evaluate conditions. If conditions are defined on the sequence flow connected with the parallel gateway, they are simply ignored.

Defining a parallel gateway needs one line of XML:

<parallelGateway id="myParallelGateway" />

The actual behavior (fork, join or both), is defined by the sequence flow connected to the parallel gateway.

For example, the model above comes down to the following XML:

<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<parallelGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" />
<sequenceFlow sourceRef="fork" targetRef="shipOrder" />

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<parallelGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

In the above example, after the process is started, two tasks will be created:

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");
TaskQuery query = taskService.createTaskQuery()
                         .processInstanceId(pi.getId())
                         .orderByTaskName()
                         .asc();

List<Task> tasks = query.list();
assertEquals(2, tasks.size());

Task task1 = tasks.get(0);
assertEquals("Receive Payment", task1.getName());
Task task2 = tasks.get(1);
assertEquals("Ship Order", task2.getName());

When these two tasks are completed the second parallel gateway will join the two executions and, as there is only one outgoing sequence flow, no concurrent paths of execution will be created, and only the Archive Order task will be active.

Note that a parallel gateway does not need to be 'balanced' (i.e. a matching number of incoming/outgoing sequence flows for corresponding parallel gateways). A parallel gateway will simply wait for all incoming sequence flows and create a concurrent path of execution for each outgoing sequence flow, not influenced by other constructs in the process model. So, the following process is legal in BPMN 2.0:

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:executionListener
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Inclusive Gateway

The Inclusive Gateway can be seen as a combination of an exclusive and a parallel gateway. Like an exclusive gateway you can define conditions on outgoing sequence flows and the inclusive gateway will evaluate them. However, the main difference is that the inclusive gateway can receive more than one sequence flow, like a parallel gateway.

The functionality of the inclusive gateway is based on the incoming and outgoing sequence flow:

  • fork: all outgoing sequence flow conditions are evaluated and for the sequence flow conditions that evaluate to 'true' the flows are followed in parallel, creating one concurrent execution for each sequence flow.
  • join: all concurrent executions arriving at the inclusive gateway wait at the gateway until an execution has arrived for each of the incoming sequence flows that have a process token. This is an important difference to the parallel gateway. So in other words, the inclusive gateway will only wait for the incoming sequence flows that will be executed. After the join, the process continues past the joining inclusive gateway.

Note that an inclusive gateway can have both fork and join behavior, if there are multiple incoming and outgoing sequence flows for the same inclusive gateway. In that case, the gateway will first join all incoming sequence flows that have a process token, before splitting into multiple concurrent paths of executions for the outgoing sequence flows that have a condition that evaluates to 'true'.

Defining an inclusive gateway needs one line of XML:

<inclusiveGateway id="myInclusiveGateway" />

The actual behavior (fork, join or both), is defined by the sequence flows connected to the inclusive gateway. For example, the model above comes down to the following XML:

<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<inclusiveGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" >
<conditionExpression xsi:type="tFormalExpression">${paymentReceived == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="fork" targetRef="shipOrder" >
<conditionExpression xsi:type="tFormalExpression">${shipOrder == true}</conditionExpression>
</sequenceFlow>

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<inclusiveGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

In the above example, after the process is started, two tasks will be created if the process variables paymentReceived == false and shipOrder == true. In case only one of these process variables equals to true only one task will be created. If no condition evaluates to true an exception is thrown. This can be prevented by specifying a default outgoing sequence flow. In the following example one task will be created, the ship order task:

HashMap<String, Object> variableMap = new HashMap<String, Object>();
variableMap.put("receivedPayment", true);
variableMap.put("shipOrder", true);

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");

TaskQuery query = taskService.createTaskQuery()
                         .processInstanceId(pi.getId())
                         .orderByTaskName()
                         .asc();

List<Task> tasks = query.list();
assertEquals(1, tasks.size());

Task task = tasks.get(0);
assertEquals("Ship Order", task.getName());

When this task is completed, the second inclusive gateway will join the two executions and since there is only one outgoing sequence flow, no concurrent paths of execution will be created, and only the Archive Order task will be active.

Note that an inclusive gateway does not need to be 'balanced' (i.e. a matching number of incoming/outgoing sequence flows for corresponding inclusive gateways). An inclusive gateway will simply wait for all incoming sequence flows and create a concurrent path of execution for each outgoing sequence flow, not influenced by other constructs in the process model.

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:executionListener
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Event-based Gateway

The event-based Gateway allows you to make a decision based on events. Each outgoing sequence flow of the gateway needs to be connected to an intermediate catching event. When process execution reaches an event-based Gateway, the gateway acts like a wait state: execution is suspended. In addition, for each outgoing sequence flow, an event subscription is created.

Note the sequence flows running out of an event-based Gateway are different than ordinary sequence flows. These sequence flows are never actually "executed". On the contrary, they allow the process engine to determine which events an execution arriving at an event-based Gateway needs to subscribe to. The following restrictions apply:

  • An event-based Gateway must have two or more outgoing sequence flows.
  • An event-based Gateway may only be connected to elements of the type intermediateCatchEvent. (Receive Tasks after an event-based Gateway are not supported by the engine yet.)
  • An intermediateCatchEvent connected to an event-based Gateway must have a single incoming sequence flow.

The following process is an example of a process with an event-based Gateway. When the execution arrives at the event-based Gateway, process execution is suspended. Additionally, the process instance subscribes to the alert signal event and creats a timer which fires after 10 minutes. This effectively causes the process engine to wait for ten minutes for a signal event. If the signal event occurs within 10 minutes the timer is canceled and execution continues after the signal. If the signal is not fired, execution continues after the timer and the signal subscription is canceled.

The corresponding xml looks like this:

<definitions>
  <signal id="alertSignal" name="alert" />
  <process id="catchSignal">
    <startEvent id="start" />

    <sequenceFlow sourceRef="start" targetRef="gw1" />

    <eventBasedGateway id="gw1" />

    <sequenceFlow sourceRef="gw1" targetRef="signalEvent" />
    <sequenceFlow sourceRef="gw1" targetRef="timerEvent" />

    <intermediateCatchEvent id="signalEvent" name="Alert">
      <signalEventDefinition signalRef="alertSignal" />
    </intermediateCatchEvent>

    <intermediateCatchEvent id="timerEvent" name="Alert">
      <timerEventDefinition>
        <timeDuration>PT10M</timeDuration>
      </timerEventDefinition>
    </intermediateCatchEvent>

    <sequenceFlow sourceRef="timerEvent" targetRef="exGw1" />
    <sequenceFlow sourceRef="signalEvent" targetRef="task" />

    <userTask id="task" name="Handle alert"/>

    <exclusiveGateway id="exGw1" />

    <sequenceFlow sourceRef="task" targetRef="exGw1" />
    <sequenceFlow sourceRef="exGw1" targetRef="end" />

    <endEvent id="end" />
  </process>
</definitions>

camunda Extensions

Attributes camunda:asyncBefore, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:executionListener
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore is set to true

Additional Resources

Start Events

A start event is a trigger for starting a process instance.

The engine supports the following types of start events:

There can a maximum of one blank or timer start event per process definition. There can be multiple message start events.

Although start events are not mandatory according to the BPMN 2.0 specification, the engine requires at least one start event to instantiate a process.

Asynchronous Instantiation

A start event may be declared as asynchronous with camunda:asyncBefore="true"

<startEvent id="startEvent" camunda:asyncBefore="true" />

This will ensure that the process engine creates a process instance when the process is instantiated, but the execution of the initial activities is not done synchronously. Instead, a job is created and asynchronously processed by the job executor. See the Asynchronous Continuations section of the User Guide for some background information.

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive, camunda:formHandlerClass, camunda:formKey, camunda:initiator
Extension Elements camunda:failedJobRetryTimeCycle, camunda:formData, camunda:formProperty,
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true
The attributes camunda:asyncBefore and camunda:initiator are only available for start events of a Process
Only one camunda:formData extension element is allowed
The attributes camunda:formHandlerClass and camunda:formKey are only available for the intital start event of a Process

None Events

None events are unspecified events, also called 'blank' events. For instance, a 'none' start event technically means that the trigger for starting the process instance is unspecified. This means that the engine cannot anticipate when the process instance must be started. The none start event is used when the process instance is started through the API by calling one of the startProcessInstanceBy... methods.

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey('invoice');

Note: a subprocess must always have a none start event.

None End Event

A 'none' end event means that the result thrown when the event is reached is unspecified. As such, the engine will not do anything besides ending the current path of execution. The XML representation of a none end event is the normal end event declaration, without any sub-element (other end event types all have a sub-element declaring the type).

<endEvent id="end" name="my end event" />

Intermediate None Event (throwing)

The following process diagram shows a simple example of an intermediate none event, which is often used to indicate some state achieved in the process.

This can be a good hook to monitor some KPI's, basically by adding an execution listener

<intermediateThrowEvent id="noneEvent">
  <extensionElements>
    <camunda:executionListener class="org.camunda.bpm.engine.test.bpmn.event.IntermediateNoneEventTest$MyExecutionListener" event="start" />
  </extensionElements>
</intermediateThrowEvent>

You can add some own code to the execution listener to maybe send some event to your BAM tool or DWH. The engine itself doesn't do anything in the event, it just passes through it.

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Message Events

Message events are events which reference a named message. A message has a name and a payload. Unlike a signal, a message event is always directed at a single recipient.

A message event definition is declared by using the messageEventDefinition element. The attribute messageRef references a message element declared as a child element of the definitions root element. The following is an excerpt of a process in which two message events are declared and referenced by a start event and an intermediate catching message event.

<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>

camunda Extensions

Attributes
Extension Elements camunda:inputOutput
Constraints

Triggering Message Events

As an embeddable process engine, the camunda engine is not concerned with the receiving part of the message. This would be environment dependent and entails platform-specific activities such as connecting to a JMS (Java Messaging Service) Queue/Topic or processing a Webservice or REST request. The reception of messages is therefore something you have to implement as part of the application or infrastructure into which the process engine is embedded.

After you have received a message, you can choose whether you employ the engine's built-in correlation or explicitly deliver the message to start a new process instance or trigger a waiting execution.

Using the runtime service's correlation methods

The engine offers a basic correlation mechanism that will either signal an execution waiting for a specific message or instantiate a process with a matching message start event. You can choose from these methods in the runtime service:

void correlateMessage(String messageName);
void correlateMessage(String messageName, String businessKey);
void correlateMessage(String messageName, Map<String, Object> correlationKeys);
void correlateMessage(String messageName, String businessKey, Map<String, Object> processVariables);
void correlateMessage(String messageName, Map<String, Object> correlationKeys, Map<String, Object> processVariables);
void correlateMessage(String messageName, String businessKey, Map<String, Object> correlationKeys, Map<String, Object> processVariables);

The messageName identifies the message as defined in the message name attribute in the process definition xml.

Correlation is successful if a single matching entity exists among the following:

  • Process Definition: A process definition matches if it can be started by a message named messageName.
  • Execution (Process Instance): An execution matches if it is waiting for a message named messageName (if provided) and its process instance matches the given businessKey and correlationKeys (if provided). The correlationKeys map is matched against the process instance variables. If messageName is not provided, any execution that matches the other criteria matches the overall correlation. This can be useful when the sending party only knows a dynamic correlation key but not the message name as defined in the process model.

Alternatively, it is possible to correlate a message to multiple matched executions and to a process definition that can be instantiated by this message in one go. Therefore you can correlate a message by using the message correlation builder as follows:

runtimeService
  .createMessageCorrelation("aMessageName")
  .correlateAll();
Current limitation:
correlationKeys is only matched against process instance variables. These are variables that are globally visible throughout the process instance. Accordingly, variables that are defined in the scope of a child execution (e.g., in a subprocess) are not considered for correlation.

In case of successful correlation, the correlated or newly created process instance is updated with the variables from the processVariables map.

Explicitly delivering a message

Alternatively, you can explicitly deliver a message to start a process instance or trigger a waiting execution.

If the message should trigger the starting of a new process instance, choose between the following methods offered by the runtime service:

ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);

These methods allow the starting of a process instance using the referenced message.

If the message needs to be received by an existing process instance, you first have to correlate the message to a specific process instance (see the next section) and then trigger the continuation of the waiting execution. The runtime service offers the following methods for triggering an execution based on a message event subscription:

void messageEventReceived(String messageName, String executionId);
void messageEventReceived(String messageName, String executionId, HashMap<String, Object> processVariables);

Querying for Message Event subscriptions

The engine supports message start events and intermediate message events.

In case of a message start event, the message event subscription is associated with a particular process definition. Such message subscriptions can be queried using a ProcessDefinitionQuery:

ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
        .messageEventSubscription("newCallCenterBooking")
        .singleResult();

As there can only be one process definition for a specific message subscription, the query always returns zero or one results. If a process definition is updated, only the newest version of the process definition has a subscription to the message event.

In case of an intermediate catch message event, the message event subscription is associated with a particular execution. Such message event subscriptions can be queried using a ExecutionQuery:

Execution execution = runtimeService.createExecutionQuery()
      .messageEventSubscriptionName("paymentReceived")
      .processVariableValueEquals("orderId", message.getOrderId())
      .singleResult();

Such queries are called correlation queries and usually require knowledge about the processes (in this case that there will be a maximum of one process instance for a given orderId).

Receiving Message Events

Message Start Event

A message start event can be used to start a process instance using a named message. This effectively allows us to select the right start event from a set of alternative start events using the message name.

When deploying a process definition with one or more message start events, the following considerations apply:

  • The name of the message start event must be unique across a given process definition, i.e., a process definition must not have multiple message start events with the same name. The engine throws an exception upon deployment of a process definition in case two or more message start events reference the same message or if two or more message start events reference messages with the same message name.
  • The name of the message start event must be unique across all deployed process definitions. The engine throws an exception upon deployment of a process definition in case one or more message start events reference a message with the same name as a message start event already deployed by a different process definition.
  • Process versioning: Upon deployment of a new version of a process definition, the message subscriptions of the previous version are canceled. This is also the case for message events that are not present in the new version.

When starting a process instance, a message start event can be triggered using the following methods on the RuntimeService:

ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object< processVariables);

The messageName is the name given in the name attribute of the message element referenced by the messageRef attribute of the messageEventDefinition. The following considerations apply when starting a process instance:

  • Message start events are only supported in top-level processes. Message start events are not supported in embedded sub processes.
  • If a process definition has multiple message start events, runtimeService.startProcessInstanceByMessage(...) allows selection of the appropriate start event.
  • If a process definition has multiple message start events and a single none start event, runtimeService.startProcessInstanceByKey(...) and runtimeService.startProcessInstanceById(...) start a process instance using the none start event.
  • If a process definition has multiple message start events and no none start event, runtimeService.startProcessInstanceByKey(...) and runtimeService.startProcessInstanceById(...) throw an exception.
  • If a process definition has a single message start event, runtimeService.startProcessInstanceByKey(...) and runtimeService.startProcessInstanceById(...) start a new process instance using the message start event.
  • If a process is started from a call activity, message start event(s) are only supported if
    • in addition to the message start event(s), the process has a single none start event
    • the process has a single message start event and no other start events.

The XML representation of a message start event is the normal start event declaration with a messageEventDefinition child-element:

<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" />

  <process id="invoiceProcess">

    <startEvent id="messageStart" >
        <messageEventDefinition messageRef="tns:newInvoice" />
    </startEvent>
    ...
  </process>

</definitions>

A process can be started using one of two different messages, this is useful if the process needs alternative ways to react to different start events but eventually continues in a uniform way.

Message Intermediate Catching Event

When a token arrives at the message intermediate catching event it will wait there until a message with the proper name arrives. As already described, the message must be handed into the engine via the appropriate API calls.

The following example shows different message events in a process model:

<intermediateCatchEvent id="message">
        <messageEventDefinition signalRef="newCustomerMessage" />
</intermediateCatchEvent>

Instead of the message intermediate catching event you might want to think about a Receive Task instead, which can serve similar purposes but is able to be used in combination with boundary events. In combination with the message intermediate catching event you might want to use an Event-based Gateway.

Message Boundary Event

Boundary events are catching events that are attached to an activity. This means that while the activity is running, the message boundary event is listening for named message. When this is caught, two things might happen, depending on the configuration of the boundary event:

  • Interrupting boundary event: The activity is interrupted and the sequence flow going out of the event is followed.
  • Non-interrupting boundary event: One token stays in the activity and an additional token is created which follows the sequence flow going out of the event.

Sending Message Events

Message Intermediate Throwing Event

A Message Intermediate Throwing event sends a message to an external service. This event has the same behavior as a Service Task.

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

camunda Extensions for messageEventDefinition

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:class, camunda:delegateExpression, camunda:expression, camunda:resultVariable
Extension Elements camunda:field, camunda:connector
Constraints One of the attributes camunda:class, camunda:delegateExpression, camunda:type or camunda:expression is mandatory
The attribute camunda:resultVariable can only be used in combination with the camunda:expression attribute

Message End Event

When process execution arrives at a Message End Event, the current path of execution is ended and a message is sent. The Message End Event has the same behavior as a Service Task.

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

camunda Extensions for messageEventDefinition

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:class, camunda:delegateExpression, camunda:expression, camunda:resultVariable
Extension Elements camunda:field, camunda:connector
Constraints One of the attributes camunda:class, camunda:delegateExpression, camunda:type or camunda:expression is mandatory
The attribute camunda:resultVariable can only be used in combination with the camunda:expression attribute

Timer Events

Timer events are events which are triggered by a defined timer. They can be used as start event, intermediate event or boundary event. Boundary events can be interrupting or not.

A timer definition must have exactly one of the following elements:

  • timeDate: This format specifies a fixed time and date in adhering to the ISO 8601 format, when the trigger will be fired. Example:

    <timerEventDefinition>
      <timeDate>2011-03-11T12:13:14Z</timeDate>
    </timerEventDefinition>
  • timeDuration: To specify how long the timer should run before it is fired, a timeDuration can be specified as a sub-element of timerEventDefinition. The format used is the ISO 8601 format (as required by the BPMN 2.0 specification). Example (interval lasting 10 days):

    <timerEventDefinition>
      <timeDuration>P10D</timeDuration>
    </timerEventDefinition>
  • timeCycle: Specifies repeating intervals, which can be useful for starting process periodically, or for sending multiple reminders for overdue user tasks. A time cycle element can be in two formats. One option is the format of recurring time duration, as specified by the ISO 8601 standard. Example (3 repeating intervals, each lasting 10 hours):

    <timerEventDefinition>
    <timeCycle>R3/PT10H</timeCycle>
    </timerEventDefinition>

    Additionally, you can specify a time cycle using cron expressions, the example below shows a trigger firing every 5 minutes, starting at full hour:

    0 0/5 * * * ?

    Please see the CronTrigger Tutorial for additional information about using cron expressions.

    Note: The first symbol denotes seconds, not minutes as in normal Unix cron.

    The recurring time duration option is better suited for handling relative timers, which are calculated in respect to some particular point in time (e.g. time when user task was started), while cron expressions can handle absolute timers - which is particularly useful for timer start events.

You can use expressions for the timer event definitions. By doing so you can influence the timer definition based on process variables. The process variables must contain the ISO 8601 (or cron for cycle type) string for the appropriate timer type.

<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport">
   <timerEventDefinition>
    <timeDuration>${duration}</timeDuration>
  </timerEventDefinition>
</boundaryEvent>

Note: timers are only fired when the Job Executor is enabled.

Camunda Extensions

Attributes camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints

Timer Start Event

A timer start event is used to create process instance at a given time. It can be used both for processes which should start only once and for processes that should start in specific time intervals.

Note: A subprocess cannot have a timer start event.

Note: A start timer event is scheduled as soon as process is deployed. There is no need to call startProcessInstanceBy..., although calling start process methods is not restricted and will cause one more starting of the process at the time of the startProcessInstanceBy... invocation.

The XML representation of a timer start event is the normal start event declaration, with a timer definition sub-element. The following example process will start 4 times, in 5 minute intervals, starting on 11th of March 2016, at 12:13 (24 hour clock system):

<startEvent id="theStart">
    <timerEventDefinition>
        <timeCycle>R4/2016-03-11T12:13/PT5M</timeCycle>
    </timerEventDefinition>
</startEvent>

and this process will start once, on a selected date:

<startEvent id="theStart">
    <timerEventDefinition>
        <timeDate>2016-03-11T12:13:14</timeDate>
    </timerEventDefinition>
</startEvent>

A note on time zones: The configuration 2016-03-11T12:13:14 does not specify a time zone. At runtime, such a date is interpreted in the local time zone of the JVM executing the process. This can be problematic in various cases, such as when running multiple Camunda nodes in different time zones or when you cannot assume the time zone the platform runs in. Furthermore, there can be glitches with respect to daylight saving time (DST). If in doubt, specify the time in UTC (e.g. 2016-03-11T12:13:14Z) or with a UTC-relative offset (e.g. 2016-03-11T12:13:14+01).

Timer Intermediate Catching Event

A timer intermediate event acts as a stopwatch. When an execution arrives in catching event activity, a timer is started. When the timer fires (e.g. after a specified interval), the sequence flow going out of the timer intermediate event is followed.

A timer intermediate event is defined as a intermediate catching event. The specific type sub-element in this case is a timerEventDefinition element.

<intermediateCatchEvent id="timer">
    <timerEventDefinition>
        <timeDuration>PT5M</timeDuration>
    </timerEventDefinition>
</intermediateCatchEvent>

Timer Boundary Event

A timer boundary event acts as a stopwatch and as an alarm clock. When an execution arrives in the activity to which the boundary event is attached, a timer is started. When the timer fires (e.g. after a specified interval), the activity is interrupted and the sequence flow going out of the timer boundary event are followed.

There is the difference between an interrupting and a non interrupting timer event. The interrupting event is the default. The non-interruptingevent leads to the original activity not being interrupted, the activity stays there. Instead, an additional execution is created and sent over the outgoing transition of the event. In the XML representation, the cancelActivity attribute is set to false:

<boundaryEvent id="escalationTimer" cancelActivity="false" attachedToRef="firstLineSupport"/>
   <timerEventDefinition>
    <timeDuration>PT4H</timeDuration>
  </timerEventDefinition>
</boundaryEvent>

Note: Timers are only fired when the Job Executor is enabled.

Known issue with boundary events

There is a known issue regarding concurrency when using boundary events of any type. Currently, it is not possible to have multiple outgoing sequence flow attached to a boundary event. A solution to this problem is to use one outgoing sequence flow that goes to a parallel gateway.

Error Events

Error events are events which are triggered by a defined error.

Important note:
A BPMN error is meant for business errors - which are different than technical exceptions. So, this is different than Java exceptions - which are, by default, handled in their own way.

Heads up!
You might want to check out the basics of Threading and Transactions in the User Guide first.

An error event definition references an error element. The following is an example of an error end event, referencing an error declaration:

<definitions>
  <error id="myError" errorCode="ERROR-OCCURED" name="ERROR-OCCURED"/>
  <!-- ... -->
  <process>
    <!-- ... -->
    <endEvent id="myErrorEndEvent">
      <errorEventDefinition errorRef="myError" />
    </endEvent>
  </process>
</definitions>

You can trigger this error event either with a throwing error event within your process definition or from Delegation Code, see the Throwing BPMN Errors from Delegation Code section of the User Guide for more information.

Another possibility to define an error is setting of the type (class name) of any Java Exception as error code. Example:

<definitions>
  <error id="myException" errorCode="com.company.MyBusinessException" name="myBusinessException"/>
  ...
  <process>
    ...
    <endEvent id="myErrorEndEvent">
      <errorEventDefinition errorRef="myException" />
    </endEvent>
  </process>
</definitions>

The exception type should only be used for business exceptions and not for technical exceptions in the process.

An error event handler references the same error element to declare that it catches the error.

Error Start Event

An error start event can only be used to trigger an Event Sub-Process - it cannot be used to start a process instance. The error start event is always interrupting.

Two optional attributes can be added to the error start event, errorRef and camunda:errorCodeVariable:

<definitions>
  <error id="myException" errorCode="com.company.MyBusinessException" name="myBusinessException"/>
  ...
  <process>
    ...
    <subprocess>
      <startEvent id="myErrorStartEvent">
        <errorEventDefinition errorRef="myException" camunda:errorCodeVariable="myErrorVariable"/>
      </startEvent>
    ...
    </subprocess>
  ...
  </process>
</definitions>
  • If errorRef is omitted, the subprocess will start for every error event that occurs.
  • The camunda:errorCodeVariable will contain the error code that was specified with the error. The value can be retrieved like any other process variable, but only if the attribute was set.

Error End Event

When process execution arrives at an error end event, the current path of execution is ended and an error is thrown. This error can be caught by a matching intermediate boundary error event. In case no matching boundary error event is found, the execution semantics defaults to the none end event semantics.

camunda Extensions

Attributes
Extension Elements camunda:inputOutput, camunda:errorCodeVariable
Constraints

Error Boundary Event

An intermediate catching error event on the boundary of an activity, or boundary error event for short, catches errors that are thrown within the scope of the activity on which it is defined.

Defining a boundary error event makes most sense on an embedded subprocess, or a call activity, as a subprocess creates a scope for all activities inside the subprocess. Errors are thrown by error end events. Such an error will propagate its parent scopes upwards until a scope is found on which a boundary error event is defined that matches the error event definition.

When an error event is caught, the activity on which the boundary event is defined is destroyed, also destroying all current executions therein (e.g. concurrent activities, nested subprocesses, etc.). Process execution continues following the outgoing sequence flow of the boundary event.

A boundary error event is defined as a typical boundary event. As with the other error events, the errorRef references an error defined outside of the process element:

<definitions>
  <error id="myError" errorCode="ERROR-OCCURED" name="name of error"/>
  <!-- ... -->
  <process>
    <!-- ... -->
    <subProcess id="mySubProcess">
      <!-- ... -->
    </subProcess>
    <boundaryEvent id="catchError" attachedToRef="mySubProcess">
      <errorEventDefinition errorRef="myError" camunda:errorCodeVariable="myErrorVariable"/>
    </boundaryEvent>
  </process>
</definitions>

The errorCode is used to match the errors that are caught:

  • If errorRef is omitted, the boundary error event will catch any error event, regardless of the errorCode of the error.
  • In case an errorRef is provided and it references an existing error, the boundary event will only catch errors with the defined error code.
  • If the errorCodeVariable is set, the error code can be retrieved using this variable.

Additional Resources

Signal Events

Signal events are events which reference a named signal. A signal is an event of global scope (broadcast semantics) and is delivered to all active handlers.

The following is an example of two separate processes communicating using signals. The first process is started if an insurance policy is updated or changed. After the changes have been reviewed by a human participant, a signal event is thrown, signaling that a policy has changed:

This event can now be caught by all process instances which are interested. The following is an example of a process subscribing to the event.

Note: It is important to understand that a signal event is broadcast to all active handlers. In of the example given above this means that all instances of the process catching the signal would receive the event.

Signal Event Definition

A signal event definition is declared using the signalEventDefinition element. The attribute signalRef references a signal element declared as a child element of the definitions root element. The following is an excerpt of a process in which a signal event is thrown and caught by intermediate events. The signalEventDefinitions reference the 'global' signal element.

<definitions>
  <!-- declaration of the signal -->
  <signal id="alertSignal" name="alert" />

  <process id="catchSignal">
    <intermediateThrowEvent id="throwSignalEvent" name="Alert">
      <!-- signal event definition -->
      <signalEventDefinition signalRef="alertSignal" />
    </intermediateThrowEvent>
    <!-- ... -->
    <intermediateCatchEvent id="catchSignalEvent" name="On Alert">
      <!-- signal event definition -->
      <signalEventDefinition signalRef="alertSignal" />
    </intermediateCatchEvent>
    <!-- ... -->
  </process>
</definitions>

Note: Contrary to other events, such error events, a signal is not consumed if it is caught. If you have two active signal boundary events catching the same signal event, both boundary events are triggered, event if they are part of different process instances.

Throwing Signal Events via API

A signal can either be thrown by a process instance using a BPMN construct or programmatically using Java API. The following methods on the org.camunda.bpm.engine.RuntimeService can be used to throw a signal programmatically:

RuntimeService.signalEventReceived(String signalName);
RuntimeService.signalEventReceived(String signalName, String executionId);

The difference between signalEventReceived(String signalName) and signalEventReceived(String signalName, String executionId) is that the first method throws the signal globally to all subscribed handlers (broadcast semantics) and the second method only delivers the signal to a specific execution.

Note: The signal event does not perform any kind of correlation to a specific process instance. On the contrary, it is broadcast to all process instances. If you need to exclusively deliver a signal to a specific process instance, do not use the throwing signal event but perform correlation manually and use signalEventReceived(String signalName, String executionId) using the appropriate query mechanisms.

Querying for Signal Event subscriptions

It is possible to query for all executions which have subscribed to a specific signal event:

List<Execution> executions = runtimeService.createExecutionQuery()
    .signalEventSubscriptionName("alert")
    .list();

We could then use the signalEventReceived(String signalName, String executionId) method to deliver the signal to these executions.

Catching Signal Events

A signal event can be caught by an intermediate catch signal event or a signal boundary event.

Note: Contrary to other events, such as the boundary error event, a boundary signal event does not only catch signal events thrown from the scope it is attached to. A signal event has a global scope (broadcast semantics), meaning that the signal can be thrown from any place, even from a different process instance.

This is straightforward in the XML:

<intermediateCatchEvent id="signal">
  <signalEventDefinition signalRef="newCustomerSignal" />
</intermediateCatchEvent>

or, alternatively:

<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
  <signalEventDefinition signalRef="alertSignal"/>
</boundaryEvent>

camunda Extensions for Catching Signal Events

Attributes
Extension Elements camunda:inputOutput
Constraints

Signal Intermediate Throwing Event

An intermediate throwing signal event throws a signal event for a defined signal.

The signal is broadcast to all active handlers (i.e. all catching signal events). Signals can be published synchronously or asynchronously.

  • In the default configuration, the signal is delivered synchronously. This means that the throwing process instance waits until the signal is delivered to all catching process instances. The catching process instances are also notified in the same transaction as the throwing process instance, which means that if one of the notified instances produces a technical error (throws an exception), all involved instances fail.
  • A signal can also be delivered asynchronously. In that case it is determined which handlers are active at the time the throwing signal event is reached. For each active handler, an asynchronous notification message (Job) is stored and delivered by the JobExecutor.

A signal intermediate event is defined as an intermediate throwing event. In this case, the specific type sub-element is a signalEventDefinition element.

<intermediateThrowEvent id="signal">
  <signalEventDefinition signalRef="newCustomerSignal" />
</intermediateThrowEvent>

An asynchronous signal event would look like this:

<intermediateThrowEvent id="signal">
  <signalEventDefinition signalRef="newCustomerSignal" camunda:async="true" />
</intermediateThrowEvent>

camunda Extensions for Signal Intermediate Throwing Event

Attributes
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints

Signal End Event

A signal end event throws a signal event for a defined signal and the current path of execution is ended. It has the same behavior as a signal intermediate throwing event.

<endEvent id="signal">
        <signalEventDefinition signalRef="newCustomerSignal" />
</endEvent>

Additional Resources

Cancel and Compensation Events

Cancel and compensation events occur in the context of the transaction subprocess. Please read that section first to understand the overall idea.

Cancel End Event

The cancel end event can only be used in combination with a transaction subprocess. When the cancel end event is reached, a cancel event is thrown which must be caught by a cancel boundary event. The cancel boundary event then cancels the transaction and triggers compensation.

Cancel Boundary Event

An attached intermediate catching cancel event on the boundary of a transaction subprocess, or, for short, a cancel boundary event, is triggered when a transaction is canceled. When the cancel boundary event is triggered, it first interrupts all executions active in the current scope. Next, it starts compensation of all active compensation boundary events in the scope of the transaction. Compensation is performed synchronously, i.e. the boundary event waits before compensation is completed before leaving the transaction. When compensation is completed, the transaction subprocess is left using the sequence flow(s) running out of the cancel boundary event.

Note: Only a single cancel boundary event is allowed for a transaction subprocess.

Note: If the transaction subprocess hosts nested subprocesses, compensation is only triggered for subprocesses that have completed successfully.

Note: In case a cancel boundary event is placed on a transaction subprocess with multi instance characteristics, if one instance triggers cancellation, the boundary event cancels all instances.

A cancel boundary event is defined as a typical boundary event:

<boundaryEvent id="boundary" attachedToRef="transaction" >
  <cancelEventDefinition />
</boundaryEvent>

Since the cancel boundary event is always interrupting, the cancelActivity attribute is not required.

Intermediate Throwing Compensation Event

An intermediate throwing compensation event can be used to trigger compensation.

Triggering compensation: Compensation can either be triggered for a designated activity or for the scope that hosts the compensation event. Compensation is performed through execution of the compensation handler associated with an activity.

  • When compensation is thrown for an activity, the associated compensation handler is executed the same amount of times the activity completed successfully.
  • If compensation is thrown for the current scope, all activities withing the current scope are compensated, which includes activities on concurrent branches.
  • Compensation is triggered hierarchically: if an activity to be compensated is a subprocess, compensation is triggered for all activities contained within the subprocess. If the subprocess has nested activities, compensation is thrown recursively. However, compensation is not propagated to the "upper levels" of the process: if compensation is triggered within a subprocess, it is not propagated to activities outside of the subprocess scope. The BPMN specification states that compensation is triggered for activities at "the same level of subprocess".
  • Compensation is performed in reverse order of execution. This means that whichever activity completed last is compensated first, etc.
  • The intermediate throwing compensation event can be used to compensate transaction subprocesses which completed successfully.

Note: If compensation is thrown within a scope which contains a subprocess and the subprocess contains activities with compensation handlers, compensation is only propagated to the subprocess if it has completed successfully when compensation is thrown. If some of the activities nested inside the subprocess have completed and have attached compensation handlers, the compensation handlers are not executed if the subprocess containing these activities is not completed yet. Consider the following example:

In this process we have two concurrent executions, one executing the embedded subprocess and one executing the "charge credit card" activity. Lets assume both executions are started and the first concurrent execution is waiting for a user to complete the "review bookings" task. The second execution performs the "charge credit card" activity and an error is thrown, which causes the "cancel reservations" event to trigger compensation. At this point the parallel subprocess is not yet completed which means that the compensation event is not propagated to the subprocess and thus the "cancel hotel reservation" compensation handler is not executed. If the user task (and thus the embedded subprocess) completes before the "cancel reservations" is performed, compensation is propagated to the embedded subprocess.

Process variables: When compensating an embedded subprocess, the execution used for executing the compensation handlers has access to the local process variables of the subprocess in the state they were in when the subprocess completed execution. To achieve this, a snapshot of the process variables associated with the scope execution (execution created for executing the subprocess) is taken. From this, a couple of implications follow:

  • The compensation handler does not have access to variables added to concurrent executions created inside the subprocess scope.
  • Process variables associated with executions higher up in the hierarchy, e.g., process variables associated with the process instance execution, are not contained in the snapshot: the compensation handler has access to these process variables in the state they are in when compensation is thrown.
  • A variable snapshot is only taken for embedded subprocesses, not for other activities.

Current limitations:

  • waitForCompletion="false" is currently unsupported. When compensation is triggered using the intermediate throwing compensation event, the event is only left after compensation completed successfully.
  • Compensation itself is currently performed by concurrent executions. The concurrent executions are started in reverse order to which the compensated activities completed. Future versions of activity might include an option to perform compensation sequentially.
  • Compensation is not propagated to sub process instances spawned by call activities.

A compensation intermediate event is defined as an intermediate throwing event. The specific type sub-element in this case is a compensateEventDefinition element.

<intermediateThrowEvent id="throwCompensation">
  <compensateEventDefinition />
</intermediateThrowEvent>

Additionally, the optional argument activityRef can be used to trigger compensation of a specific scope / activity:

<intermediateThrowEvent id="throwCompensation">
  <compensateEventDefinition activityRef="bookHotel" />
</intermediateThrowEvent>

camunda Extensions

Attributes
Extension Elements camunda:inputOutput
Constraints

Compensation Boundary Event

An attached intermediate catching compensation on the boundary of an activity, or, for short, a compensation boundary event, can be used to attach a compensation handler to an activity.

The compensation boundary event must reference a single compensation handler using a directed association.

A compensation boundary event has a different activation policy than other boundary events. Other boundary events, such as the signal boundary event are activated when the activity they are attached to is started. When the activity is left, they are deactivated and the corresponding event subscription is canceled. The compensation boundary event is different. The compensation boundary is activated when the activity it is attached to completes successfully. At this point, the corresponding subscription to compensation events is created. The subscription is removed either when a compensation event is triggered or when the corresponding process instance ends. This leads to the following points:

  • When compensation is triggered, the compensation handler associated with the compensation boundary event is invoked the same amount of times that the activity it is attached to completed successfully.
  • If a compensation boundary event is attached to an activity with multiple instance characteristics, a compensation event subscription is created for each instance.
  • If a compensation boundary event is attached to an activity which is contained inside a loop, a compensation event subscription is created for each time the activity is executed.
  • If the process instance ends, the subscriptions to compensation events are canceled.

Note: The compensation boundary event is not supported on embedded subprocesses.

A compensation boundary event is defined as a typical boundary event:

<boundaryEvent id="compensateBookHotelEvt" attachedToRef="bookHotel" >
  <compensateEventDefinition />
</boundaryEvent>

<association associationDirection="One" id="a1"  sourceRef="compensateBookHotelEvt" targetRef="undoBookHotel" />

<serviceTask id="undoBookHotel" isForCompensation="true" camunda:class="..." />

As the compensation boundary event is activated after the activity has completed successfully, the cancelActivity attribute is not supported.

Additional Resources

Terminate Events

A terminate event ends the complete scope where the event is raised and all inner scopes.

It is useful if you had a parallel split in your process before and you want to consume all tokens that are currently available immediately.

If you use it on the process instance level, the whole process is terminated. On a subprocess level the current scope and all inner processes will be terminated.

Terminate Event Definition

A terminate event is modeled as a end event with an additional definition element to mark the termination:

<process id="someProcess">
  <!-- ... -->
    <endEvent id="EndEvent_2" name="Tweet rejected">
      <terminateEventDefinition id="TerminateEventDefinition_1"/>
    <endEvent>
  <!-- ... -->
</process>

Additional Resources

Embedded Subprocess

A Subprocess is an activity that contains other activities, gateways, events, etc. which itself forms a process that is part of the bigger process. A Subprocess is completely defined inside a parent process (that's why it's often called an embedded Subprocess).

Subprocesses have two major use cases:

  • Subprocesses allow hierarchical modeling. Many modeling tools allow that subprocesses can be collapsed, hiding all the details of the subprocess and displaying a high-level end-to-end overview of the business process.
  • A subprocess creates a new scope for events. Events that are thrown during execution of the subprocess can be caught by a boundary event on the boundary of the subprocess, thus creating a scope for that event, limited to the subprocess.

Using a subprocess does impose some constraints:

  • A subprocess can only have one none start event, no other start event types are allowed. A subprocess must have at least one end event. Note that the BPMN 2.0 specification allows to omit the start and end events in a subprocess, but the current engine implementation does not support this.
  • Sequence flows can not cross subprocess boundaries.

A subprocess is visualized as a typical activity, i.e., a rounded rectangle. In case the subprocess is collapsed, only the name and a plus-sign are displayed, giving a high-level overview of the process:

In case the subprocess is expanded, the steps of the subprocess are displayed within the subprocess boundaries:

One of the main reasons to use a subprocess is to define a scope for a certain event. The following process model shows this: both the investigate software and investigate hardware tasks need to be done in parallel, but both tasks need to be done within a certain time, before Level 2 support is consulted. Here, the scope of the timer (i.e., which activities must be done in time) is constrained by the subprocess.

A subprocess is defined by the subprocess element. All activities, gateways, events, etc. that are part of the subprocess, need to be enclosed within this element.

<startEvent id="outerStartEvent" />
<!-- ... other elements ... -->
<subProcess id="subProcess">
   <startEvent id="subProcessStart" />
   <!-- ... other subprocess elements ... -->
   <endEvent id="subProcessEnd" />
</subProcess>

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

Call Activity

BPMN 2.0 makes a distinction between an embedded subprocess and a call activity. From a conceptual point of view, both will call a subprocess when process execution arrives at the activity.

The difference is that the call activity references a process that is external to the process definition, whereas the subprocess is embedded within the original process definition. The main use case for the call activity is to have a reusable process definition that can be called from multiple other process definitions. Although not yet part of the BPMN specification, it is also possible to call a CMMN case definition.

When process execution arrives at the call activity, a new process instance is created, which is used to execute the subprocess, potentially creating parallel child executions as within a regular process. The main process instance waits until the subprocess is completely ended, and continues the original process afterwards.

A call activity is visualized the same way as a collapsed embedded subprocess, however with a thick border. Depending on the modeling tool, a call activity can also be expanded, but the default visualization is the collapsed representation.

A call activity is a regular activity that requires a calledElement which references a process definition by its key. In practice, this means that the id of the process is used in the calledElement:

<callActivity id="callCheckCreditProcess" name="Check credit" calledElement="checkCreditProcess" />

Note that the process definition of the subprocess is resolved at runtime. This means that the subprocess can be deployed independently from the calling process, if needed.

CalledElement Binding

In a call activity the calledElement attribute contains the process definition key as reference to the subprocess. This means that the latest process definition version of the subprocess is always called. To call another version of the subprocess it is possible to define the attributes calledElementBinding and calledElementVersion in the call activity. Both attributes are optional.

CalledElementBinding has three different values:

  • latest: always call the latest process definition version (which is also the default behaviour if the attribute isn't defined)
  • deployment: if called process definition is part of the same deployment as the calling process definition, use the version from deployment
  • version: call a fixed version of the process definition, in this case calledElementVersion is required. The version number can either be specified in the BPMN XML or returned by an expression (see custom extensions)
<callActivity id="callSubProcess" calledElement="checkCreditProcess"
  camunda:calledElementBinding="latest|deployment|version"
  camunda:calledElementVersion="17">
</callActivity>

Passing variables

You can pass process variables to the subprocess and vice versa. The data is copied into the subprocess when it is started and copied back into the main process when it ends.

<callActivity id="callSubProcess" calledElement="checkCreditProcess" >
  <extensionElements>
    <camunda:in source="someVariableInMainProcess" target="nameOfVariableInSubProcess" />
    <camunda:out source="someVariableInSubProcss" target="nameOfVariableInMainProcess" />
  </extensionElements>
</callActivity>

Furthermore, you can configure the call activity so that all process variables are passed to the subprocess and vice versa. The process variables have the same name in the main process as in the subprocess.

<callActivity id="callSubProcess" calledElement="checkCreditProcess" >
  <extensionElements>
    <camunda:in variables="all" />
    <camunda:out variables="all" />
  </extensionElements>
</callActivity>

It is possible to use expressions here as well:

<callActivity id="callSubProcess" calledElement="checkCreditProcess" >
  <extensionElements>
    <camunda:in sourceExpression="${x+5}" target="y" />
    <camunda:out sourceExpression="${y+5}" target="z" />
  </extensionElements>
</callActivity>

So, in the end z = y+5 = x+5+5.

Source expressions are evaluated in the context of the called process instance. That means, in cases where calling and called process definition belong to different process applications, context like Java classes, Spring or CDI beans is resolved from the process application the called process definition belongs to.

Passing Business Key

You can pass the business key to the subprocess. The data is copied into the subprocess when it is started. You can not give back the business key to the parent process because the business key is not changeable.

<callActivity id="callSubProcess" calledElement="checkCreditProcess" >
  <extensionElements>
    <camunda:in businessKey="#{execution.processBusinessKey}" />
  </extensionElements>
</callActivity>

Example

The following process diagram shows a simple handling of an order. Since, for example, the billing could be common to many other processes, it is modeled as a call activity.

The XML looks as follows:

<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="shipping" />

<callActivity id="shipping" name="Shipping" calledElement="shippingProcess" />
<sequenceFlow id="flow2" sourceRef="shipping" targetRef="billing" />

<callActivity id="billing" name="Billing" calledElement="billingProcess" />
<sequenceFlow id="flow3" sourceRef="billing" targetRef="end" />

<endEvent id="end" />

There is nothing special about the process definition of the subprocess. It could also be used without being called from another process.

Create a Case Instance

A call activity can also be used to create a new CMMN case instance as a subordinate of the corresponding process instance. The call activity completes as soon as the created case instance reaches the state COMPLETED for the first time. In contrast to calling a BPMN process, the attribute caseRef instead of the attribute calledElement must be used to reference a case definition by its key. This means that the latest case definition version is always called.

To call another version of a case definition it is possible to define the attributes caseBinding and caseVersion in the call activity. Both attributes are optional.

CaseBinding has three different values:

  • latest: always call the latest case definition version (which is also the default behaviour if the attribute isn't defined)
  • deployment: if called case definition is part of the same deployment as the calling process definition, use the version from deployment
  • version: call a fixed version of the case definition, in this case caseVersion is required
<callActivity id="callSubProcess" camunda:caseRef="checkCreditCase"
  camunda:caseBinding="latest|deployment|version"
  camunda:caseVersion="17">
</callActivity>

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:calledElementBinding, camunda:calledElementVersion, camunda:caseBinding, camunda:caseRef, camunda:caseVersion, camunda:exclusive
Extension Elements camunda:in, camunda:out, camunda:failedJobRetryTimeCycle
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true
The attribute camunda:calledElementVersion should only be set if the attribute camunda:calledElementBinding equals version
The attribute calledElement cannot be used in combination with the attribute camunda:caseRef and vice versa.
The attribute camunda:caseVersion should only be set if the attribute camunda:caseBinding equals version

Additional Resources

Event Subprocess

The Event subprocess is a subprocess that is triggered by an event. An Event subprocess can be added at the process level or at any subprocess level. The event used to trigger an event subprocess is configured using a start event. Therefore, none start events are not supported for Event subprocesses. An Event subprocess might be triggered using events like message events, error events, signal events, timer events, or compensation events. The subscription to the start event is created when the scope (process instance or subprocess) hosting the Event subprocess is created. The subscription is removed when the scope is ended.

An Event subprocess may be interrupting or non-interrupting. An interrupting subprocess cancels any executions in the current scope. A non-interrupting Event subprocess spawns a new concurrent execution. While an interrupting Event subprocess can only be triggered once for each activation of the scope hosting it, a non-interrupting Event subprocess can be triggered multiple times. Whether the subprocess is interrupting or non-interrupting is configured using the start event which triggers the Event subprocess.

An Event subprocess may not have any incoming or outgoing sequence flows. As an Event subprocess is triggered by an event, an incoming sequence flow makes no sense. When an Event subprocess is ended, either the current scope is ended (in case of an interrupting Event subprocess), or the concurrent execution spawned for the non-interrupting subprocess is ended.

The Event subprocess is visualized as an embedded subprocess with a dotted outline.

It is represented using XML in the same way as an embedded subprocess. Additionally, the attribute triggeredByEvent must have the value true:

<subProcess id="eventSubProcess" triggeredByEvent="true">
  <!-- ... -->
</subProcess>
  • Event subprocesses triggered using an Error Start Event, Signal Start Event, Timer Start Event and Message Start Event are supported.

Example

The following is an example of an Event subprocess triggered using an Error Start Event. The Event subprocess is located at the "process level", i.e., is scoped to the process instance:

This is what the Event subprocess looks like in XML:

<subProcess id="eventSubProcess" triggeredByEvent="true">
  <startEvent id="catchError">
    <errorEventDefinition errorRef="error" />
  </startEvent>
  <sequenceFlow id="flow2" sourceRef="catchError" targetRef="taskAfterErrorCatch" />
  <userTask id="taskAfterErrorCatch" name="Provide additional data" />
</subProcess>

As already stated, an Event subprocess can also be added to an embedded subprocess. If it is added to an embedded subprocess, it becomes an alternative to a boundary event. Consider the two following process diagrams. In both cases the embedded subprocess throws an error event. Both times the error is caught and handled using a user task.

as opposed to:

In both cases the same tasks are executed. However, there are differences between both modeling options:

  • The embedded subprocess is executed using the same execution which executed the scope it is hosted in. This means that an embedded subprocess has access to the variables local to it's scope. When using a boundary event, the execution created for executing the embedded subprocess is deleted by the sequence flow leaving the boundary event. This means that the variables created by the embedded subprocess are not available anymore.
  • When using an Event subprocess, the event is completely handled by the subprocess it is added to. When using a boundary event, the event is handled by the parent process.

These two differences can help you decide whether a boundary event or an embedded subprocess is better suited for solving a particular process modeling / implementation problem.

Additional Resources

Transaction Subprocess

A transaction subprocess is an embedded subprocess which can be used to group multiple activities to a transaction. A transaction is a logical unit of work which allows grouping of a set of individual activities, so that they either succeed or fail collectively.

A transaction can have three different outcomes, with these three possible outcomes:

  • A transaction is successful if it is neither canceled not terminated by a hazard. If a transaction subprocess is successful, it is left using the outgoing sequenceflow(s). A successful transaction might be compensated if a compensation event is thrown later in the process.

    Note: just as "ordinary" embedded subprocesses, a transaction may be compensated after successful completion using an intermediate throwing compensation event.

  • A transaction is canceled if an execution reaches the cancel end event. In that case all executions are terminated and removed. A single remaining execution is then set to the cancel boundary event, which triggers compensation. After compensation is completed the transaction subprocess is left, using the outgoing sequence flow(s) of the cancel boundary event.

  • A transaction is ended by a hazard if an error event is thrown which is not caught within the scope of the transaction subprocess. (This also applies if the error is caught on the boundary of the transaction subprocess.) In this case, compensation is not performed.

The following diagram illustrates the three different outcomes:

A transaction subprocess is represented in xml using the transaction element:

<transaction id="myTransaction" >
  <!-- ... -->
</transaction>
Relation to ACID transactions: It is important not to confuse the BPMN transaction subprocess with technical (ACID) transactions. The BPMN transaction subprocess is not a way to scope technical transactions. In order to understand transaction management in camunda BPM, read the Transactions in Processes section of the User Guide.

A BPMN transaction differs from a technical transaction in the following ways:

  • While an ACID transaction is typically short lived, a BPMN transaction may take hours, days or even months to complete. (Consider a case where one of the activities grouped by a transaction is a usertask; typically, people have longer response times than applications. Or, in another situation, a BPMN transaction might wait for some business event to occur, like the fact that a particular order has been fulfilled.) Such operations usually take considerably longer to complete than updating a record in a database or storing a message using a transactional queue.

  • Because it is impossible to scope a technical transaction to the duration of a business activity, a BPMN transaction typically spans multiple ACID transactions.

  • Since a BPMN transaction spans multiple ACID transactions, we loose ACID properties. Consider the example given above. Let's assume the "book hotel" and the "charge credit card" operations are performed in separate ACID transactions. Let's also assume that the "book hotel" activity is successful. Now we have an intermediate inconsistent state because we have performed a hotel booking but have not yet charged the credit card. Now, in an ACID transaction, we would also perform different operations sequentially and therefore also have an intermediate inconsistent state. What is different here is that the inconsistent state is visible outside of the scope of the transaction. For example, if the reservations are made using an external booking service, other parties using the same booking service might already see that the hotel is booked. This means that when implementing business transactions, we completely lose the isolation property (granted, we usually also relax isolation when working with ACID transactions to allow for higher levels of concurrency, but there we have fine grained control and intermediate inconsistencies are only present for very short periods of times).

  • A BPMN business transaction can also not be rolled back in the traditional sense. As it spans multiple ACID transactions, some of these ACID transactions might already be committed at the time the BPMN transaction is canceled. At that point they cannot be rolled back anymore.

Since BPMN transactions are long-running in nature, the lack of isolation and a rollback mechanism needs to be dealt with differently. In practice there is usually no better solution than to deal with these problems in a domain specific way:

  • The rollback is performed using compensation. If a cancel event is thrown in the scope of a transaction, the effects of all activities that executed successfully and have a compensation handler are compensated.
  • The lack of isolation is also often dealt with by using domain specific solutions. For instance, in the example above, a hotel room might appear to be booked to a second customer before we have actually made sure that the first customer can pay for it. Since this might be undesirable from a business perspective, a booking service might choose to allow for a certain amount of overbooking.
  • In addition, since the transaction can be aborted in case of a hazard, the booking service has to deal with the situation where a hotel room is booked but payment is never attempted (since the transaction was aborted). In that case, the booking service might choose a strategy where a hotel room is reserved for a maximum period of time and, if payment is not received until then, the booking is canceled.

To sum it up: while ACID transactions offer a generic solution to such problems (rollback, isolation levels and heuristic outcomes), we need to find domain specific solutions to these problems when implementing business transactions.

Current limitations: The BPMN specification requires that the process engine reacts to events issued by the underlying transaction protocol and, in case a transaction is canceled, if a cancel event occurs, in the underlying protocol. As an embeddable engine, the camunda engine currently does not support this. (For some ramifications of this, see the paragraph on consistency below.)

Consistency on top of ACID transactions and optimistic concurrency: A BPMN transaction guarantees consistency in the sense that either all activities compete successfully, or, if some activity cannot be performed, the effects of all other successful activities are compensated. So either way, we end up in a consistent state. However, it is important to recognize that in camunda BPM, the consistency model for BPMN transactions is superposed on top of the consistency model for process execution. The camunda engine executes processes in a transactional way. Concurrency is addressed using optimistic locking. In the engine BPMN, error, cancel and compensation events are built on top of the same ACID transactions and optimistic locking. For example, a cancel end event can only trigger compensation if it is actually reached. It is not reached if some undeclared exception is thrown by a service task before. The effects of a compensation handler can not be committed if some other participant in the underlying ACID transaction sets the transaction to the state rollback-only. Also, when two concurrent executions reach a cancel end event, compensation might be triggered twice and fail with an optimistic locking exception. All of this is to say that when implementing BPMN transactions in the core engine, the same set of rules apply as when implementing "ordinary" processes and subprocesses. So, to effectively guarantee consistency, it is important to implement processes in a way that takes the optimistic, transactional execution model into consideration.

camunda Extensions

Attributes camunda:asyncBefore, camunda:asyncAfter, camunda:exclusive
Extension Elements camunda:failedJobRetryTimeCycle, camunda:inputOutput
Constraints The camunda:exclusive attribute is only evaluated if the attribute camunda:asyncBefore or camunda:asyncAfter is set to true

Additional Resources

BPMN 2.0 Custom Extensions

The BPMN 2.0 standard is a good thing for all parties involved. End-users don't suffer from a vendor lock-in that comes from depending on a proprietary solution. Frameworks, and particularly open-source frameworks such as camunda BPM, can implement a solution that has the same (and often better implemented ;-)) features as those of a big vendor. Due to the BPMN 2.0 standard, the transition from one tool to the other works seamlessly.

The downside of a standard however, is the fact that it is always the result of many discussions and compromises between different companies (and often visions). As a developer reading the BPMN 2.0 XML of a process definition, sometimes it feels like certain constructs or ways to do things are too cumbersome. Since camunda BPM places ease of development as a top-priority, we introduced our own BPMN extensions. These extensions are new constructs or ways to simplify certain constructs that are not in the BPMN 2.0 specification.

Although the BPMN 2.0 specification clearly states that it was made for custom extension, we make sure that:

  • The prerequisite of such a custom extension is that there must always be a simple transformation to the standard way of doing things. So when you decide to use a custom extension you don't have to be afraid that there is no way back.
  • When using a custom extension it is always clearly indicated by giving the new XML element, attribute, etc. the camunda: namespace prefix.
  • The goal of these extensions is to eventually push them back into a newer version of the BPMN specification or at least trigger a discussion that can lead to a revision of that specific BPMN construct.

So, whether you want to use a custom extension or not is completely up to you. Several factors will influence this decision (graphical editor usage, company policy, etc.). We only provide them since we believe that some points in the standard can be done simpler or more efficiently. Feel free to give us (positive and/or negative) feedback on our extensions or to post new ideas for custom extensions. Who knows, some day your idea might pop up in the specification.

camunda Extension Elements

The following elements are extension elements for the camunda namespace http://activiti.org/bpmn.

camunda:connector

Description The configuration of a camunda connector.
Attributes
Constraints The camunda:connectorId child element is required and must identify a connector implementation known to the process engine
Parent elements Service Task, Business Rule Task, Send Task, Message Event Definition of Message Intermediate Throwing Event or Message End Event,
Child elements camunda:inputOutput, camunda:connectorId

camunda:connectorId

Description The unique identifier of the connector type to instantiate.
Attributes
Constraints The connector type has to be known to the process engine
Parent elements camunda:connector
Child elements

camunda:constraint

Description Metadata of an individual validation constraint for a form field (see Form Field Validation).
Attributes name The name of the form field constraint type
config The configuration of the form field constraint type
Constraints The name attribute must be one of the known validators (required, minlength, maxlength, min, max, readonly or validator)
Parent elements camunda:validation
Child elements

camunda:entry

Description A single entry of a map structure. Can contain a constant, expression, script, list or another map.
Attributes key The key of the entry in the map
Constraints The key attribute is required
Parent elements camunda:map
Child elements camunda:list, camunda:map, camunda:script

camunda:executionListener

Description Add an execution listener to an event.
Attributes event The type of the event for which the listener is called
class see camunda:class
expression see camunda:expression
delegateExpression see camunda:delegateExpression
Constraints The event attribute is required (except for transitions) and must be one of the task events: start or end
One of the attributes class, expression or delegateExpression is mandatory
Parent elements Process, Task, Service Task, Send Task, User Task, Business Rule Task, Script Task, Receive Task, Manual Task, Exclusive Gateway, Sequence Flow, Parallel Gateway, Inclusive Gateway, Event Based Gateway, Start Event, Intermediate Catch Event, Intermediate Throw Event, End Events, Boundary Events, Embedded Subprocess, Call Activity, Event Subprocess, Transaction Subprocess
Child elements camunda:field, camunda:script

camunda:expression

Description Defines an expression to inject in delegated classes (see Field Injection).
Attributes
Text Content The expression to inject
Constraints
Parent elements camunda:field
Child elements

camunda:failedJobRetryTimeCycle

Description Defines the custom retry schedule for a failed job (see Failed Jobs).
Attributes
Text Content The retry time cycle value
Constraints The configuration follows the ISO 8601 standard for repeating time intervals
Parent elements Task, Service Task, Send Task, User Task, Business Rule Task, Script Task, Receive Task, Timer Start Event, Timer Intermediate Catching Event, Timer Boundary Event, Intermediate Signal Throw Event, Embedded Subprocess, Call Activity, Transaction Subprocess
Child elements

camunda:field

Description Defines the value to inject in delegated classes (see Field Injection).
Attributes name The name of the field
expression The value of the field as expression
stringValue The value of the field as String
Constraints Only one attribute of stringValue and expression or one of the child elements string and expression can be used
Parent elements Service Task, Business Rule Task, Send Task, Message Event Definition of Message Intermediate Throwing Event or Message End Event, camunda:taskListener, camunda:executionListner
Child elements camunda:expression, camunda:string

camunda:formData

Description Metadata to define fields of a form, which are used to generate task forms (see Generated Task Forms).
Attributes
Constraints
Parent elements Start Event, User Task
Child elements camunda:formField

camunda:formField

Description Metadata to define a single form field (see Generated Task Forms).
Attributes id The id of the form field, corresponding to the name of a process variable
label The label to be displayed next to the form field
type The type of the form field
datePattern The pattern of a date type form field
defaultValue The value to be used as a default (pre-selection) for the field
Constraints The attribute id may not be empty
The attribute type can be one of the known form field types (string, long, boolean, date or enum) or a custom one
The attribute datePattern can only be used if the type attribute is set to date
The child element camunda:properties is only allowed once
The child element camunda:validation is only allowed once
The child elements camunda:values can only be used if the type attribute is set to enum
Parent elements camunda:formData
Child elements camunda:properties, camunda:validation, camunda:value

camunda:formProperty

Description Metadata to define a form field (Deprecated use camunda:formData).
Attributes id The key used to submit the property through the API
name The display label of the property
type The type of the property
required True if the form field is required (default: false)
readable True if the form field is readable and will be displayed (default: true)
writeable True if the form field is writeable (default: true)
variable Specifies the process variable on which the variable is mapped
expression Specifies an expression that maps the property, e.g. ${street.address}
datePattern The pattern of a date type form field
default The default value or expression of the property
Constraints The id attribute is required
The attribute type can be one of the known types (string, long, boolean, date or enum) or a custom one
The attribute datePattern can only be used if the type attribute is set to date
The child elements camunda:values can only be used if the type attribute is set to enum
Parent elements Start Event, User Task
Child elements camunda:value

camunda:in

Description The element specifies variables which should be passed to the subprocess, see passing variables for more information.
Attributes source A name of a process variable to be passed in
sourceExpression An expression to be evaluated and passed in
variables Can be set to all to pass all process variables in
target Name of the process variable inside the subprocess instance
businessKey Set the business key of the subprocess process instance
Constraints Only one of the attributes source, sourceExpression, variables or businessKey can be used
The attribute target is required if the source or sourceExpression attribute is used
Parent elements Call Activity
Child elements

camunda:inputParameter

Description An single input mapping for the activity. If the element has no child element the text content of this element is mapped into the activity. The text content can be a constant string value or an expression. If no child element or text content exists the variable inside the activity is set to the special value null.
Attributes name The name of the variable inside the activity.
Constraints The name attribute is required.
The element can have one child element, a constant string or an expression as text content.
Parent elements camunda:inputOutput
Child elements camunda:list, camunda:map, camunda:script

camunda:inputOutput

Description The element describes an input/output mapping for the activity.
Attributes
Constraints
Parent elements All Tasks, All Events (except Start and Boundary Events), Embedded Subprocess, Transaction Subprocess, camunda:connector
Child elements camunda:inputParameter, camunda:outputParameter

camunda:list

Description A list structure. If the list contains multiple values they should be added as text content of child elements. Which child elements are use is arbitrary, e.g..:
<camunda:list>
  <camunda:value>one</camunda:value>
  <camunda:value>two</camunda:value>
  <camunda:value>three</camunda:value>
</camunda:list>

Also a camunda:script element can be used as a list element. The return value of the script is added to the list. Furthermore, lists can contain nested lists and maps.
Attributes
Constraints Multiple values have to be encapsulated in child elements.
Parent elements camunda:inputParameter, camunda:outputParameter, camunda:list, camunda:entry
Child elements Any child element, camunda:list, camunda:map

camunda:map

Description A map structure. The entries can be constants, expressions, scripts, nested maps and lists.
Attributes
Constraints
Parent elements camunda:inputParameter, camunda:outputParameter, camunda:list, camunda:entry
Child elements camunda:entry

camunda:out

Description The element specifies variables which should be passed back from the subprocess, see passing variables for more information.
Attributes source A name of a process variable to be passed back
sourceExpression An expression to be evaluated and passed back
variables Can be set to all to pass all subprocess variables back
target Name of the process variable inside the subprocess instance
Constraints Only one of the attributes source, sourceExpression, variables or businessKey can be used
The attribute target is required if the source or sourceExpression attribute is used
Parent elements Call Activity
Child elements

camunda:outputParameter

Description An single output mapping for the activity. If the element has no child element, the text content of this element is mapped out of the activity. The text content can be a constant string value or an expression. If no child element or text content exists, the variable outside of the activity is set to the special value null.
Attributes name The name of the variable outside of the activity.
Constraints The name attribute is required.
The element can have one child element, a constant string or an expression as text content.
Parent elements camunda:inputOutput
Child elements camunda:list, camunda:map, camunda:script

camunda:potentialStarter

Description Defines which users or groups can start the process.
Attributes
Constraints
Parent elements Process
Child elements resourceAssignmentExpression

camunda:properties

Description A key value list of properties which be can be interpreted freely.
Attributes
Constraints
Parent elements Base Element, camunda:formField
Child elements camunda:property

camunda:property

Description A key value pair which can be interpreted freely.
Attributes id The id of the form field property
name The name of the property
value The value of the property
Constraints If the property belongs to a camunda:formField extension element, only the attributes id and value are used.
If the parent camunda:properties element is directly added as an extension element, for example by the camunda Modeler, only the attributes name and value are used.
Parent elements camunda:properties
Child elements

camunda:script

Description A script element. The script is executed and the return value is used as mapping value.
Attributes scriptFormat The format identifier, normally the language of the script source code
resource equivalent to camunda:resource
Constraints The scriptFormat attribute is required
If the resource attribute is used, no source code text content is allowed
Parent elements camunda:inputParameter, camunda:outputParameter, camunda:entry, camunda:list, camunda:executionListener, camunda:taskListener
Child elements

camunda:string

Description Defines a String value to inject in delegated classes (see Field Injection).
Attributes
Text Content The String value to inject
Constraints
Parent elements camunda:field
Child elements

camunda:taskListener

Description Add a task listener to a task event.
Attributes event The type of the event for which the listener is called
class see camunda:class
expression see camunda:expression
delegateExpression see camunda:delegateExpression
Constraints The event attribute is required and must be one of the task events: create, assignment, complete or delete
One of the attributes class, expression or delegateExpression is mandatory
Parent elements User Task
Child elements camunda:field, camunda:script

camunda:validation

Description Metadata to define a list of validation constraints for form fields (see Form Field Validation).
Attributes
Constraints
Parent elements camunda:formField
Child elements camunda:constraint

camunda:value

Description Possible values of a form field with the type enum.
Attributes id The id of the value
name The name of the value
Constraints
Parent elements camunda:formField, camunda:formProperty
Child elements

camunda Extension Attributes

The following attributes are extension attributes for the camunda namespace http://activiti.org/bpmn.

camunda:assignee

Description The attribute specifies a human performer of a User Task.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values The name of a performer as java.lang.String or an expression which evaluates to a java.lang.String e.g. ${initiator}
Default Value
BPMN 2.0 Elements User Task

camunda:asyncAfter

Description Specifies an asynchronous contiuation after an activity, see Asynchronous Continuations for more information.
Type java.lang.Boolean
Possible Values true, false
Default Value false
BPMN 2.0 Elements Start Events, End Events, Intermediate Throw Events, Intermediate Catch Events, Task, Service Task, Send Task, User Task, Business Rule Task, Script Task, Receive Task, Manual Task, Embedded Subprocess, Call Activity, Transaction Subprocess, Parallel Gateway, Inclusive Gateway, Exclusive Gateway

camunda:asyncBefore

Description Specifies an asynchronous continuation before an activity, see Asynchronous Continuations for more information.
Type java.lang.Boolean
Possible Values true, false
Default Value false
BPMN 2.0 Elements Start Events, End Events, Intermediate Throw Events, Intermediate Catch Events, Task, Service Task, Send Task, User Task, Business Rule Task, Script Task, Receive Task, Manual Task, Embedded Subprocess, Call Activity, Transaction Subprocess, Parallel Gateway, Event Based Gateway, Inclusive Gateway, Exclusive Gateway

camunda:calledElementBinding

Description The attribute specifies which process definition version of the subprocess the call activity calls. If the value is version the attribute camunda:calledElementVersion is required, see Called Element Binding for more information.
Type java.lang.String
Possible Values latest, deployment, version
Default Value
BPMN 2.0 Elements Call Activity

camunda:calledElementVersion

Description The attribute specifies which process definition version of the subprocess the call activity calls if the camunda:calledElementBinding is set to version, see Called Element Binding for more information.
Type java.lang.Integer or org.camunda.bpm.engine.delegate.Expression
Possible Values A concrete version of all deployed version numbers of the subprocess to call as java.lang.Integer or an expression which evaluates to a java.lang.Integer e.g. ${versionToCall}
Default Value
BPMN 2.0 Elements Call Activity

camunda:candidateGroups

Description The attribute specifies which group(s) will be candidate for performing the User Task.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values Comma separated list of group ids as java.lang.String or expressions that evaluate to a java.lang.String or a java.util.Collection of java.lang.String, e.g. management or management, ${accountancyGroupId()}
Default Value
BPMN 2.0 Elements User Task

camunda:candidateStarterGroups

Description The attribute specifies which group(s) will be able to start the process.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values Comma separated list of group ids as java.lang.String or expressions that evaluate to a java.lang.String or a java.util.Collection of java.lang.String, e.g. management or management, ${accountancyGroupId()}
Default Value
BPMN 2.0 Elements Process

camunda:candidateStarterUsers

Description The attribute specifies which user(s) will be able to start the process.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values Comma separated list of user ids as java.lang.String or expressions that evaluate to a java.lang.String or a java.util.Collection of java.lang.String, e.g. kermit, gonzo or ${ldapService.findAllSales()}
Default Value
BPMN 2.0 Elements Process

camunda:candidateUsers

Description The attribute specifies which user(s) will be candidate for performing the User Task.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values Comma separated list of user ids as java.lang.String or expressions that evaluate to a java.lang.String or a java.util.Collection of java.lang.String, e.g. kermit, gonzo or ${ldapService.findAllSales()}
Default Value
BPMN 2.0 Elements User Task

camunda:caseBinding

Description The attribute specifies which case definition version of the subcase the call activity calls. If the value is version the attribute camunda:caseVersion is required, see Case Binding for more information.
Type java.lang.String
Possible Values latest, deployment, version
Default Value
BPMN 2.0 Elements Call Activity

camunda:caseRef

Description The attribute references a case definition by its key to call.
Type java.lang.String
Possible Values
Default Value
BPMN 2.0 Elements Call Activity

camunda:caseVersion

Description The attribute specifies which case definition version of the subcase the call activity calls if the camunda:caseBinding is set to version, see Case Binding for more information.
Type java.lang.Integer
Possible Values All deployed version numbers of the subprocess to call
Default Value
BPMN 2.0 Elements Call Activity

camunda:class

Description The attribute specifies which Java class will be executed at runtime. The stated class must implement a Java delegate interface.
Type java.lang.String
Possible Values Fully qualified Java class name of a class which implements a Java Delegate interface, e.g org.camunda.bpm.MyJavaDelegate
Default Value
BPMN 2.0 Elements Service Task, Business Rule Task, Send Task, Message Event Definition of Message Intermediate Throwing Event or Message End Event, camunda:taskListener, camunda:executionListner

camunda:collection

Description The attribute specifies a collection, where for each element, an instance will be created. See Multiple Instance for more information.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values The name of a java.util.Collection process variable as java.lang.String or an Expression which evaluates to the name of a collection
Default Value
BPMN 2.0 Elements Multi Instance Loop Characteristics of Task, Embedded Subprocess, Call Activity, Transaction Subprocess

camunda:delegateExpression

Description The attribute allows specification of an expression which must resolve to an object that implements the corresponding interface (see delegation code).
Type org.camunda.bpm.engine.delegate.Expression
Possible Values Expression which evaluates to a Java class implementing a delegation interface, e.g. ${myJavaDelegate} or #{myTaskListener}
Default Value
BPMN 2.0 Elements Service Task, Business Rule Task, Send Task, Message Event Definition of Message Intermediate Throwing Event or Message End Event, camunda:taskListener, camunda:executionListner

camunda:dueDate

Description The attribute specifies the initial due date of a User Task when it is created.
Type org.camunda.bpm.engine.delegate.Expression
Possible Values An expression which evaluates to a java.util.Date, java.util.String (ISO 8601 formatted) or null, e.g. ${dateVariable}
Default Value
BPMN 2.0 Elements User Task

camunda:elementVariable

Description The attribute specifies the process variable which will be set on each created instance, containing an element of the specified collection see Multiple Instance for more information.
Type java.lang.String
Possible Values The name of a process variable as java.lang.String
Default Value
BPMN 2.0 Elements Multi Instance Loop Characteristics of Task, Embedded Subprocess, Call Activity, Transaction Subprocess

camunda:errorCodeVariable

Description The attribute specifies a process variable which will be set if an error has been received by the error start or boundary event, see Error Events for more information.
Type java.lang.String
Possible Values The error code of an error defined in the process definition.
Default Value
BPMN 2.0 Elements Error Events

camunda:exclusive

Description The attribute specifies that jobs should be executed exclusively. See Exclusive Jobs for more information.
Type java.lang.Boolean
Possible Values true, false
Default Value true
BPMN 2.0 Elements Start Events, End Events, Intermediate Throw Events, Intermediate Catch Events, Task, Service Task, Send Task, User Task, Business Rule Task, Script Task, Receive Task, Manual Task, Embedded Subprocess, Call Activity, Transaction Subprocess, Parallel Gateway, Event Based Gateway, Inclusive Gateway, Exclusive Gateway

camunda:expression

Description The attribute defines an expression which will be evaluated at runtime.
Type org.camunda.bpm.engine.delegate.Expression
Possible Values Expression, e.g. ${gender == 'male' ? 'Mr.' : 'Mrs.'} or #{printer.printMessage()}
Default Value
BPMN 2.0 Elements Service Task, Business Rule Task, Send Task, Message Event Definition of Message Intermediate Throwing Event or Message End Event, camunda:taskListener, camunda:executionListner

camunda:formHandlerClass

Description The attribute specifies the class that will be called during the parsing of the form information of a Start Event or User Task.
Type java.lang.String
Possible Values Fully qualified Java class name of a class which implements the org.camunda.bpm.engine.impl.form.handler.StartFormHandler or org.camunda.bpm.engine.impl.form.handler.TaskFormHandler interface, e.g. org.camunda.bpm.MyUserTaskFormHandler
Default Value
BPMN 2.0 Elements Initial Start Event of a Process, User Task

camunda:formKey

Description The attribute specifies a form resource. See task forms for more information.
Type java.lang.String
Possible Values A java.lang.String of a form resource which can be evaluated by the Tasklist
Default Value
BPMN 2.0 Elements Initial Start Event of a Process, User Task

camunda:initiator

Description The attribute specifies a process variable in which the user id of the process initiator is set.
Type java.lang.String
Possible Values A process variable name to save the process initiator
Default Value
BPMN 2.0 Elements Start Event of a Process

camunda:priority

Description The attribute specifies the initial priority of a User Task when it is created.
Type org.camunda.bpm.engine.delegate.Expression
Possible Values An expression which evaluates to a java.lang.Number or a java.lang.String which represents a number or null, e.g. ${dateVariable}
Default Value
BPMN 2.0 Elements User Task

camunda:resource

Description The attribute specifies an external resource. The resource can be part of the deployment or exists in the classpath. To specify the type of resource, a URL scheme like prefix deployment:// resp. classpath:// can be supplied. If the scheme is omitted, it is assumed that the resource exists in the classpath.
Type java.lang.String or org.camunda.bpm.engine.delegate.Expression
Possible Values The path to a resource or an expression which returns the path. Optional the path can start with an URL like scheme classpath:// or deployment:// to specify where to find the resource. If omitted the resource is assumed to exists in the classpath.
Default Value
BPMN 2.0 Elements Script Task

camunda:resultVariable

Description

The attribute specifies the process variable to save the return value of a camunda:expression.

Note that when you use camunda:resultVariable in a multi-instance construct, for example in a multi-instance subprocess, the result variable is overwritten every time the task completes unless the variable is a local variable in the scope of the multi-instance construct. This can lead to seemingly random behavior.

This is a known issue. As a workaround, a local variable can be declared by adding an execution listener to the subprocess' start event that initializes the variable as null.

Type java.lang.String
Possible Values The name of a process variable to save the return value
Default Value
BPMN 2.0 Elements Service Task, Business Rule Task, Script Task, Send Task, Message Event Definition of Message Intermediate Throwing Event or Message End Event,

camunda:type

Description The attribute specifies which built-in task implementation to use. Currently an email and a shell service task exists.
Type java.lang.String
Possible Values mail, shell
Default Value
BPMN 2.0 Elements Service Task, Business Rule Task, Send Task