Working with process variables
In this topic, you will find out how to dynamically create your processes using variables.
Useful information on process variables
Process variables are data containing information on a process instance. The following process variables are included in every process instance:
dv_initiator: A process variable of data type Identity. The process variable refers to the identity of the user who has started the process instance.
dv_start_time: A process variable of data type String. The process variable includes the UTC string of the time at which the process instance was started from the point of view of the application. The time at which the application was instructed to start the process instance applies. As the actual (technical) start of the instance is performed asynchronously, the time included in the variable may vary.
Using other process variables
You can use these variables for special purposes:
dv_sender: A process variable of data type Identity. The process variable refers to the identity of the user who is used as the sender of user activities.
dv_attachment: A process variable of data type DmsObject or other. The process variable includes a link which is added as an attachment to all user activities.
dv_decision: A process variable of the type String. For tasks, this text is highlighted as a decision in the process protocol.
dv_comment: A process variable of the type String. For tasks, this text is highlighted as a comment in the process protocol.
Warning
The process variable dv_attachment is predefined with the data type DmsObject . If you want to use a different URI than that for an object of the DMS app, you need to change the value of the data type to String.
Defining process variables
In the process definition, you can define variables that are used within a process. Defined variables can be automatically validated and, if necessary, converted at the appropriate interfaces of the application.
You can define the following variables within a process:
General process variable: A variable which is valid in the entire process. You can specify whether it is a start variable.
Local process variable: A variable with a scope that is limited to a single process activity.
Service variables: Input or output variables of a process service.
A variable definition contains the following information:
Property | Possible values | Example |
---|---|---|
Name | [A-Za-z][A-Za-z0-9_]* | myVariable (name property) |
Start variable | myStartVariable* (name property) | |
Data type |
| String (value property) |
Single or multi-value | Single value: String (value property) Multi-value: [String] (value property) | |
Mandatory variable | Single value: String! (value property) Multi-value: [String] (value property) |
Note
Specifics of the Object data type:
You can only define a variable of the type Object in a process.
A variable of the type Object must not contain a multi-value.
Variables of the type Object are not logged.
Warning
Please consider the following important notes when using process variables:
Name prefix "dv_": You must not use the name prefix dv_ for variables. These variables are reserved for internal variables. You may use the name prefix dv_ only when overwriting the variable definition dv_attachment .
Changing variable definitions when switching the version: If you change the data type of a variable or switch between a single value and a multi-value between different versions of a process, errors may occur in the execution of the process after the migration. These errors occur if existing process instances already contain values for the corresponding variables in the previous definition. After migrating to the new version, these values lose their validation. Always make sure that no process instance requiring migration is affected when changing the variable definition.
Note
You cannot delete a variable which is defined as a mandatory variable via the interface for changes to variables. If the mandatory variable is also a start variable, a user always needs to transfer a valid value when a process instance is started. If he does not transfer a valid value, the request will be rejected with the error code 400.
For data type Number the following restrictions apply:
Minimum | Maximum | Decimal places | Accuracy |
---|---|---|---|
-1e16 | 1e16 | 5 | 15 places |
The non-primitive data types use the following notation:
Data type | Notation |
---|---|
Identity | For users: identity:///identityprovider/scim/users/<someUserId> For groups: identity:///identityprovider/scim/groups/<someGroupId> |
DmsObject | dmsObject:///dms/r/<repositoryId>/o2/<dmsObjectId> |
URL | https://www.d-velop.de (max. 2,000 characters) |
Object | { "myKey" : "myValue" } (JSON-String, max. 50 KB) |
Variables are defined as a BPMN extension in the form of Camunda properties. In the BPMN model, you define general process and service variables directly in the process node. You define local process variables in the node of the activity in which they are to apply.
General process and service variables
<process id="myProcess" name="Process with variable declaration" isExecutable="true"> <extensionElements> <camunda:properties> <camunda:property name="variable:myVariable" value="[String]!" /> <!-- Name: "myVariable", Type: "String", Multiple: true, Mandatory: true, Startvariable: false --> <camunda:property name="variable:myStartVariable*" value="String" /> <!-- Name: "myStartVariable", Type: "String", Multiple: false, Mandatory: false, Startvariable: true--> <camunda:property name="variable:someUserTaskOutput" value="String" /> <!-- Name: "someUserTaskOutput", Type: "String", Multiple: false, Mandatory: false, Startvariable: false --> <camunda:property name="service:/myservice:in:input" value="String!" /> <!-- Name: "input", Type: "String", Multiple: false, Mandatory: true --> <camunda:property name="service:/myservice:out:output" value="Number!" /> <!-- Name: "output", Type: "Number", Multiple: false, Mandatory: true --> </camunda:properties> </extensionElements> </userTask>
Local process variable
<userTask id="userTask" name="User Task"> <extensionElements> <camunda:inputOutput> <camunda:inputParameter name="someInput">user task input which is only available within this user task scope</camunda:inputParameter> <camunda:outputParameter name="someUserTaskOutput">user task output which will be written to process scope</camunda:outputParameter> </camunda:inputOutput> <camunda:properties> <camunda:property name="variable:someInput" value="String" /> </camunda:properties> </extensionElements> </userTask>
Using process variables
When modeling your own processes, you can use process variables to create dynamic processes. When getting started with process variables, it is useful to create a simple process with one user activity first. This process will e.g. look like this:
![]() |
The BPMN of this sample process is structures as follows. To simplify the example, the graphic information on the BPMN diagram is not included in this BPMN sample file.
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" targetNamespace="" exporter="d.velop process modeler"> <process id="GettingStarted" name="Beispiel: Einstieg" isExecutable="true"> <startEvent id="start"/> <userTask id='task_hello_world' name='Hello World' camunda:candidateUsers="${variables.get('dv_initiator')}" /> <sequenceFlow id="s1" sourceRef="start" targetRef="task_hello_world" /> <sequenceFlow id="s2" sourceRef="task_hello_world" targetRef="end" /> <endEvent id="end"/> </process> </definitions>
Now add a new variable definition to this process definition.
Adding a variable definition
To be able to use a process variable, you need to add it to the process definition. In the process definition, you add the BPMN items extensionElements and camunda:properties to the BPMN item process. To define the process variable, then add the item camunda:property to the BPMN item camunda:properties.
This example shows how to add the variable message of data type String:
<process id="GettingStarted" name="Beispiel: Einstieg" isExecutable="true"> <extensionElements> <camunda:properties> <camunda:property name="variable:message" value="String" /> </camunda:properties> </extensionElements> ... </process>
Explanation of the properties
name: This property defines the name of the process variable. The value is always preceded by the prefix variable:.
value: This property defines the data type of the process variable.
Using the process variable
You can now use the variable message for the name of the user activity, so that this name is displayed to the user in the task list. To do so, replace the existing test in the property name of the user activity with the method for access to the variable message:
<process id="GettingStarted" name="Beispiel: Einstieg" isExecutable="true"> ... <userTask id="task_hello_world" name="${variables.get('message')}" camunda:candidateUsers="${variables.get('dv_initiator')}" /> ...
You can now define the value of the variable e.g. for the start of the process.
Determining process variables
Using the object variables you can access the process variables. In each case, the call is executed using the notation variables.<methodName>( <Parameter>).
get( String variableName)
The method determines the value for the variable with the entered variable name. For variables with a multi-value, the values are returned in a list (collection).
getDisplayValue( String variableName)
The method determines the value for the variable with the entered variable name. An according conversion will take place here depending on the data type.
For variables with a multi-value, the converted values are returned in a string, separated by commas. If the data type of the variables is Number, the converted values are returned in a string, separated by semicolons.
Data type | Actual value | Returned value |
---|---|---|
String | "some value" | "some value" |
Number | 1.23 | "1.23" |
Identity | identity:///identityprovider/scim/users/userIdOfJohnSmith | "John Smith" (displayName- property of the user, name- property for groups in the d.ecs identity provider) |
DmsObject | dmsObject:///dms/r/someRepo/o2/T000000001 | "/dms/r/someRepo/o2/T000000001" |
Object | {"myKey":"myValue"} | "{\"myKey\":\"myValue\"}" (JSON-String) |
getObjectValue(String variableName, String objectPath)
This method can only be used for variables of the type Object. It allows you to access individual parts of the object.
Example:
Supposed there is a variable of the Object type with the name "myObjectVariable" and the following value:
{ "my" : { "object" : { "path" : 123 } } }
The method getObjectValue can be used to determine the following parts of the objects, for example:
Method call | Returned value |
---|---|
getObjectValue("myObjectVariable", "my.object.path") | 123 |
getObjectValue("myObjectVariable", "my.object") | {"path":123} |
Generating multi-values
You can use the object collections to generate a list (collection) from individual values, e.g. to assign a multi-value to a variable. Generating a list from individual values is useful if you want to register several recipients as a constant in a user activity.
Example
${collections.from( "identity:///identityprovider/scim/users/user1", "identity:///identityprovider/scim/users/user")}
from( Object...objects)
The method generates a list (collection) with the transferred individual values.
Useful information on the scope of process variables
Process variables always have a specific scope within a process instance. Depending on the scope, read and write access will be possible.
In every process instance, there is a universal scope which comprises the entire process. All other scopes, such as user or service activities, have read access to the variables in the universal scope.
Additional scopes are generated at the following points:
Gateways with parallel paths
Multi-instance constructs
Subprocesses
Input/output mapping or timer events during user activities
Service activities
Read access
Read access to process variables (e.g. the use in an expression) is possible independently of the scope. If no value is found in the current scope, the section above it is searched until a value has been found.
Write access
If you want to change values (e.g. in a user activity with output mapping), the value is always applied to the current scope. Other scopes, e.g. along other branches in the process, are not impacted by this until the end of this scope. The changes are transferred to all other scopes only at the end of the current scope.
End of scopes
At the end of a scope (e.g. when joining parallel branches or at the end of a subprocess), the variables of this scope are discarded. You must configure an output mapping before you can apply variables to a scope located higher in the hierarchy. In the process, the call hierarchy is run through until a scope that already contains this variable is found. This run starts from the current item and works its way towards the top. The new value is then applied to this scope. If the variable is completely new, it is then written to the scope of the entire process.
Warning
Please note that a timer event generates its own scope during user activities. If you do not define a dedicated input/output mapping for the user activity, all variables of this scope will be applied to the higher scope when the activity is completed.
Impact on process monitoring
The view of a token always shows the variables of the current scope. Changes to the variables are only applied in this scope.
Most tokens have their own scope. The only exception are user activities for which no input/output mapping was configured and which are not executed in parallel to other activities. Theses tokens have the same scope as the token directly above them.
In the view of the token without its own scope, you can find a link to a token from the section above it. When you select this link, you can view the variables of the linked scope.