# Technical Documentation: flowable/flowable-engine

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/flowable/flowable-engine)

### Overview (README.md)

Flowable
========

[](https://central.sonatype.com/search?q=g:org.flowable%20%26%26%20%28a:flowable-engine%20a:flowable-cmmn-engine%20a:flowable-dmn-engine%29)
[](https://hub.docker.com/r/flowable/flowable-rest)
[](https://github.com/flowable/flowable-engine/blob/main/LICENSE)



Homepage: https://www.flowable.org/

## flowable / flowəb(ə)l /
* a compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.
* a lightning fast, tried and tested BPMN process engine, CMMN case engine and DMN rule engine written in Java.  It is Apache 2.0 licensed open source, with a committed community.
* can run embedded in a Java application, or as a service on a server, a cluster, and in the cloud.  It integrates perfectly with Spring.  With a rich Java and REST API, it is the ideal engine for orchestrating human or system activities.

## Introduction

### License

Flowable is distributed under the Apache V2 license (http://www.apache.org/licenses/LICENSE-2.0.html).

### Download

The Flowable downloads can be found on https://www.flowable.org/downloads.html.

### Sources

The distribution contains most of the sources as jar files. The source code of Flowable can be found on https://github.com/flowable/flowable-engine.

### JDK 17+

Flowable V7 runs on a Java higher than or equal to version 17. Use the JDK packaged with your Linux distribution or go to [adoptium.net](https://adoptium.net/) and click on the *Latest LTS Release* button. There are installation instructions on that page as well. To verify that your installation was successful, run `java -version` on the command line. That should print the installed version of your JDK.

[Flowable V6](https://github.com/flowable/flowable-engine/tree/flowable6.x) is still maintained and supports Java 8+.

### Flowable Design

Flowable offers a free to use Flowable Cloud Design application, which you can use to model CMMN, BPMN, DMN and other model types. You can register via the Flowable account registration page to get started https://www.flowable.com/account/open-source.

### Contributing

Contributing to Flowable: https://github.com/flowable/flowable-engine/wiki.

### Reporting problems

Every self-respecting developer should have read this link on how to ask smart questions: http://www.catb.org/~esr/faqs/smart-questions.html.

After you've done that you can post questions and comments on https://forum.flowable.org and create issues in https://github.com/flowable/flowable-engine/issues.

---

### Public Api README (`docs/public-api/README.md`)

# Flowable Rest API Documentation

This project contains information and tooling about Flowable Public Rest API.

## Introduction

Flowable includes a set of Public REST API to the Flowable Engine.

We distinct currently 4 groups of APIs 
+ **Process API** : Provides access to most of the Flowable services
+ **Decision API** : Provides access to the Flowable DMN engine
+ **Form API** : Provides access to the Flowable Form engine
+ **Content API** : Provides access to the Flowable Content Services
 
### Quick Installation
 
Flowable REST API can be installed by deploying the **flowable-rest.war** or **flowable-task.war**  file to a servlet container like Apache Tomcat.

It's also possible to use **Docker** images to easily boot up an environment.
```bash 
docker run -p8080:8080 flowable/flowable-rest
```

### Quick Integration

The Flowable REST API can also be used in another web-application by including the servlet and its mapping in your application and add all flowable-rest dependencies to the classpath.

### Contribution & Documentation Issues

If you spot a documentation issue please raise an issue directly on [Github](https://github.com/flowable/flowable-engine/issues) or create a [Pull Request](https://github.com/flowable/flowable-engine/pulls)

# References

**[OpenAPI](https://github.com/OAI/OpenAPI-Specification)** is a standard specification to describe a REST API. It's vendor neutral and backed by the [OpenAPI initiative](https://www.openapis.org/) which includes [many software companies](https://www.openapis.org/membership/members) (Google, Microsoft, IBM, Atlassian...). 

## Swagger Specification V2

You can retrieve the Swagger Specification for Flowable API by following links below.

| API Name | Syntax Validation  | 
|:---:|:---:|
| [Process API](references/swagger/process/flowable-swagger-process.yaml) | <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/process/flowable-swagger-process.yaml"/>  |  
| [Form API](references/swagger/form/flowable-swagger-form.yaml) |  <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/form/flowable-swagger-form.yaml"/> |  
| [Decision API](references/swagger/decision/flowable-swagger-decision.yaml) |  <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/decision/flowable-swagger-decision.yaml"/> | 
| [Content API](references/swagger/content/flowable-swagger-content.yaml) | <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/content/flowable-swagger-content.yaml"/>  | 


## Open API Specification V3

You can retrieve the OpenApi Specification (V3) for Flowable API by following links below.


| API Name |
|:---:|
| [Process API](references/openapi/process/flowable-oas-process.yaml) |    
| [Form API](references/openapi/form/flowable-oas-form.yaml) | 
| [Decision API](references/openapi/decision/flowable-oas-decision.yaml) |  
| [Content API](references/openapi/content/flowable-oas-content.yaml) |   

# Tools

To help developers discovering & using Flowable API, we provide a set of tools ready to use.

## [Flowable OpenAPI Specification Generator](tools/flowable-oas-generator)

Utility project to generate automatically the swagger definition from the source code.

## [Flowable Rest Asciidoc](tools/flowable-rest-asciidoc)

Utility project to generate asciidoc based on OAS files.

## [Flowable Swagger UI](tools/flowable-swagger-ui)

Utility project to build a WAR file for Swagger UI.

## [Flowable Slate](tools/flowable-slate)

Utility project to create a beautiful static web site for REST API docs.

## [Flowable Swagger Codegen](tools/flowable-swagger-codegen)

Utility project to generate client sdk to interact with Flowable Rest API.

---

### Docusaurus Website README (`docs/docusaurus/website/README.md`)

To install docusaurus globally:

`yarn global add docusaurus`

To run the docs in dev mode: `yarn start`

To build the docs: `yarn build`

---

### Public Api References README (`docs/public-api/references/README.md`)

# Flowable Rest API Documentation

In this folder you will retrieve all OpenAPI Specifications for Flowable Public REST API.

# References

**[OpenAPI](https://github.com/OAI/OpenAPI-Specification)** is a standard specification to describe a REST API. It's vendor neutral and backed by the [OpenAPI initiative](https://www.openapis.org/) which includes [many software companies](https://www.openapis.org/membership/members) (Google, Microsoft, IBM, Atlassian...). 

## Swagger Specification V2

You can retrieve the Swagger Specification (V2) for Flowable API by following links below.

| API Name | Syntax Validation  | 
|:---:|:---:|
| [Process API](swagger/process/flowable-swagger-process.yaml) | <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/process/flowable-swagger-process.yaml">  |  
| [Form API](swagger/form/flowable-swagger-form.yaml) |  <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/form/flowable-swagger-form.yaml"> |  
| [Decision API](swagger/decision/flowable-swagger-decision.yaml) |  <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/decision/flowable-swagger-decision.yaml"> | 
| [Content API](swagger/content/flowable-swagger-content.yaml) | <img src="http://online.swagger.io/validator?url=https://raw.githubusercontent.com/flowable/flowable-engine/master/docs/public-api/references/swagger/content/flowable-swagger-content.yaml">  | 


## OpenAPI Specification V3

You can retrieve the OpenApi Specification (V3) for Flowable API by following links below.


| API Name |
|:---:|
| [Process API](openapi/process/flowable-oas-process.yaml) |    
| [Form API](openapi/form/flowable-oas-form.yaml) | 
| [Decision API](openapi/decision/flowable-oas-decision.yaml) |  
| [Content API](openapi/content/flowable-oas-content.yaml) |

---

### Public Api References Openapi README (`docs/public-api/references/openapi/README.md`)

## Important Notice

**Please don't copy & paste generated OpenApi Specification files inside this folder.**

### Work in progress

OpenApi Specification files **are not currently complete** for the Flowable Public API.

---

### Public Api References Swagger README (`docs/public-api/references/swagger/README.md`)

## Important Notice

**Please don't copy & paste automatically generated OpenApi Specification files inside this folder.**

### Explanation

OpenApi Specifications files for Flowable REST API are mostly generated automatically [by Swagger/OAS annotation](https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X) from inside the code.

Sadly due to Swagger V2 design and Flowable REST API design some usages/use cases are not well supported.

It implies the OAS files automatically generated ([by Flowable OAS Generator project for example](../../tools/flowable-oas-generator)) contains some issues which must be fixed manually. 

OAS Files contained here in this folder represents the stable documentation version of the APIs and can be used by external tools.

Restrictions due to design considerations are marked inside the documentation.

#### For Information

In source code OAS issues are generally marked with **FIXME OASv3**

---

### Public Api Tools Flowable Oas Generator README (`docs/public-api/tools/flowable-oas-generator/README.md`)

# Flowable OpenAPI Specification Generator

## Introduction

Utility project to generate automatically the swagger definition from the source code.

## Usage

Build for flowable-rest in localhost
```bash 
mvn clean package
```

Build for flowable-task in localhost
```bash 
mvn clean package -Ptask-app
```

Build for flowable-task with a specific hostname
```bash 
mvn clean package -Ptask-app -Dswagger.host=10.0.0.1:9090
```

---

### Public Api Tools Flowable Rest Asciidoc README (`docs/public-api/tools/flowable-rest-asciidoc/README.md`)

# Flowable Rest API - Asciidoc Generator

## Introduction

Utility project to generate asciidoc based on swagger definitions.


## Usage

Execute **mvn install**

Results are in **target/asciidoc** folder


## Integration (manual) with userguide


For a specific API like **process**
+ Go to **target/asciidoc/process**
+ Copy **ch14-REST.adoc**
+ Paste (and overwrite) to **userguide/src/bpmn**
+ Execute html & pdf generation.

---

### Public Api Tools Flowable Slate README (`docs/public-api/tools/flowable-slate/README.md`)

# Flowable Slate UI

## Introduction

Utility project to build a static web site for the Public REST API

## Tooling

We're using the [widdershins](https://github.com/mermade/widdershins) library to translate swagger definitions into slate compatible markdown. This needs to be installed on your system too: 

```ruby 
npm install [-g] widdershins
```

We're using the **sed** GNU Linux command. This needs to be installed on your system too (if not present): 

On Mac Os 
```ruby 
brew install gnu-sed --with-default-names
```

## Usage

Execute **generate.sh** to generate slate website based on Swagger (v2) API Specification.
or
Execute **generate-oas.sh** to generate slate website based on OpenAPI API Specification.

We recommend to use **generate-oas.sh**.

For each API a website will be available in **target/slate** folder.

Drop the folder into a web server or open index.html directly in your web browser.

---

### Public Api Tools Flowable Swagger Codegen README (`docs/public-api/tools/flowable-swagger-codegen/README.md`)

# Flowable Swagger Codegen

## Introduction

Utility project to build platform specific client SDK to interact with Flowable Rest API

## Usage

**Using build.xml**

Simply select run the *[java|swift|js|kotlin].all* goal and it will generates a client SDK skeleton.
All generated files will be available in root project **target** folder.

## Recommendation

Please use this tool with caution to create an SDK skeleton project.

Check the generated code and ensure it fits your project architecture and coding guidelines.

---

### Public Api Tools Flowable Swagger Ui README (`docs/public-api/tools/flowable-swagger-ui/README.md`)

# Flowable Swagger UI

## Introduction

Utility project to build a WAR file for Swagger UI.

## Usage

Run a build
```bash 
mvn clean install
```


## Build

Build the WAR file with Swagger Reference 
```bash 
mvn clean package 
```

Build the WAR file with generated OAS 
```bash 
mvn clean package -Pimport-generator
```

---

### Docusaurus Docs Disclaimer (`docs/docusaurus/docs/disclaimer.md`)

---
id: disclaimer
title: Disclaimer
---

Flowable may change, amend or delete information contained in its documents at any time and without formal arrangement. Documents and other informational items concerning a release of a Flowable product that has not yet been officially released by Flowable are non-binding and may be incomplete or contain errors. Flowable strives to provide complete and exact information in its documents. If permitted by applicable law, Flowable takes no responsibility for the accuracy of the issued informational items and documentation and does not provide any warranty for their content. Flowable assumes no liability for any direct, indirect or incidental damages incurred by the use of its documents and informational items. Documents or informational items do not change or amend the contractual terms and conditions regarding Flowable products.

---

### Docusaurus Docs Header Rest (`docs/docusaurus/docs/header-rest.md`)

---
id: header-rest
title: General Flowable REST principles
---

## Installation and Authentication

Flowable includes a REST API to the Flowable engine that can be installed by deploying the flowable-rest.war file to a servlet container like Apache Tomcat. However, it can also be used in another web-application by including the servlet (and/or its mappings) in your application and add all flowable-rest dependencies to the classpath.

By default the Flowable engine will connect to an in-memory H2 database. You can change the database settings in the flowable-app.properties file in the *WEB-INF/META-INF/flowable-app* folder. The REST API uses JSON format (<http://www.json.org>) and is built upon the Spring MVC (<http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html>).

All REST-resources require a valid user with the *rest-access-api* privilege to be authenticated by default. If any valid user should be able to call the REST API, the *flowable.rest.app.authentication-mode* can be set to *any-user* (this was the default in older versions of Flowable).

A default user that can access the REST API can be configured by settings the following properties:

    flowable.rest.app.admin.user-id=rest-admin
    flowable.rest.app.admin.password=test
    flowable.rest.app.admin.first-name=Rest
    flowable.rest.app.admin.last-name=Admin

When the REST app boots up, the user is created if it doesn’t exist or fetched otherwise. This user will be given the *access-rest-api* privilege which is needed by default to access the REST API. **Do not forget to change the password of this user afterwards**. If the *flowable.rest.app.admin.user-id* is not set, no users or privileges will be created. So, after the initial setup, removing this property will not remove the user nor the privilege that has been configured before.

Basic HTTP access authentication is used, so you should always include a *Authorization: Basic …​==* HTTP-header when performing requests or include the username and password in the request-url (for example, *<http://username:password@localhost:8080/xyz>*).

**We recommend that you use Basic Authentication in combination with HTTPS.**

## Configuration

The Flowable REST web application uses Spring Java Configuration for starting the Flowable Form engine, defining the basic authentication security using Spring security, and to define the variable converters for specific variable handling.
A small number of properties can be defined by changing the flowable-app.properties file you can find in the WEB-INF/META-INF/flowable-app/flowable-app.properties folder.
If you need more advanced configuration options there’s the possibility to override the default Spring beans in XML in the flowable-custom-context.xml file you can also find in the WEB-INF/classes folder.
An example configuration is already in comments in this file. This is also the place to override the default RestResponseFactory by defining a new Spring bean with the name restResponsefactory and use your custom implementation class for it.

## Usage in Tomcat

Due to [default security properties on Tomcat](http://tomcat.apache.org/tomcat-8.0-doc/security-howto.html), **escaped forward slashes (%2F and %5C) are not allowed by default (400-result is returned).** This may have an impact on the deployment resources and their data-URL, as the URL can potentially contain escaped forward slashes.

When issues are experienced with unexpected 400-results, set the following system-property:

*-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW\_ENCODED\_SLASH=true*

It’s best practice to always set the **Accept** and **Content-Type** (in case of posting/putting JSON) headers to **application/json** on the HTTP requests described below.

## Methods and return-codes

<table>
<caption>HTTP-methods and corresponding operations</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>GET</p></td>
<td><p>Get a single resource or get a collection of resources.</p></td>
</tr>
<tr class="even">
<td><p>POST</p></td>
<td><p>Create a new resource. Also used for executing resource-queries which have a too complex request-structure to fit in the query-URL of a GET-request.</p></td>
</tr>
<tr class="odd">
<td><p>PUT</p></td>
<td><p>Update properties of an existing resource. Also used for invoking actions on an existing resource.</p></td>
</tr>
<tr class="even">
<td><p>DELETE</p></td>
<td><p>Delete an existing resource.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>HTTP-methods response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200 - Ok</p></td>
<td><p>The operation was successful and a response has been returned (GET and PUT requests).</p></td>
</tr>
<tr class="even">
<td><p>201 - Created</p></td>
<td><p>The operation was successful and the entity has been created and is returned in the response-body (POST request).</p></td>
</tr>
<tr class="odd">
<td><p>204 - No content</p></td>
<td><p>The operation was successful and entity has been deleted and therefore there is no response-body returned (DELETE request).</p></td>
</tr>
<tr class="even">
<td><p>401 - Unauthorized</p></td>
<td><p>The operation failed. The operation requires an Authentication header to be set. If this was present in the request, the supplied credentials are not valid or the user is not authorized to perform this operation.</p></td>
</tr>
<tr class="odd">
<td><p>403 - Forbidden</p></td>
<td><p>The operation is forbidden and should not be re-attempted. This implies an issue with authorization not authentication, it’s an operation that is not allowed. Example: deleting a task that is part of a running process is not allowed and will never be allowed, regardless of the user or process/task state.</p></td>
</tr>
<tr class="even">
<td><p>404 - Not found</p></td>
<td><p>The operation failed. The requested resource was not found.</p></td>
</tr>
<tr class="odd">
<td><p>405 - Method not allowed</p></td>
<td><p>The operation failed. The method is not allowed for this resource. For example, trying to update (PUT) a deployment-resource will result in a 405 status.</p></td>
</tr>
<tr class="even">
<td><p>409 - Conflict</p></td>
<td><p>The operation failed. The operation causes an update of a resource that has been updated by another operation, which makes the update no longer valid. Can also indicate a resource that is being created in a collection where a resource with that identifier already exists.</p></td>
</tr>
<tr class="odd">
<td><p>415 - Unsupported Media Type</p></td>
<td><p>The operation failed. The request body contains an unsupported media type. Also occurs when the request-body JSON contains an unknown attribute or value that doesn’t have the right format/type to be accepted.</p></td>
</tr>
<tr class="even">
<td><p>500 - Internal server error</p></td>
<td><p>The operation failed. An unexpected exception occurred while executing the operation. The response-body contains details about the error.</p></td>
</tr>
</tbody>
</table>

The media-type of the HTTP-responses is always application/json unless binary content is requested (for example, deployment resource data), the media-type of the content is used.

## Error response body

When an error occurs (both client and server, 4XX and 5XX status-codes) the response body contains an object describing the error that occurred. An example for a 404-status when a task is not found:

    {
      "statusCode" : 404,
      "errorMessage" : "Could not find a task with id '444'."
    }

## Request parameters

### URL fragments

Parameters that are part of the URL (for example, the deploymentId parameter in http://host/flowable-rest/process-api/repository/deployments/{deploymentId})
need to be properly escaped (see [URL-encoding or Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding)) in case the segment contains special characters. Most frameworks have this functionality built in, but it should be taken into account. Especially for segments that can contain forward-slashes (for example, deployment resource), this is required.

### Rest URL query parameters

Parameters added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/process-api/repository/deployments?name=Deployment) can have the following types and are mentioned in the corresponding REST-API documentation:

<table>
<caption>URL query parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. Can contain any valid characters that are allowed in URLs. In the case of a XXXLike parameter, the string should contain the wildcard character % (properly URL-encoded). This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Boolean</p></td>
<td><p>Parameter representing a boolean value. Can be either true or false. All other values other than these will cause a '405 - Bad request' response.</p></td>
</tr>
<tr class="odd">
<td><p>Date</p></td>
<td><p>Parameter representing a date value. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (e.g. 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

### JSON body parameters

<table>
<caption>JSON parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. In the case of a XXXLike parameter, the string should contain the wildcard character %. This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value, using a JSON number. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value, using a JSON number. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Date</p></td>
<td><p>Parameter representing a date value, using a JSON text. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (for example, 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

### Paging and sorting

Paging and order parameters can be added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/process-api/repository/deployments?sort=name).

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>sort</p></td>
<td><p>different per query implementation</p></td>
<td><p>Name of the sort key, for which the default value and the allowed values are different per query implementation.</p></td>
</tr>
<tr class="even">
<td><p>order</p></td>
<td><p>asc</p></td>
<td><p>Sorting order which can be 'asc' or 'desc'.</p></td>
</tr>
<tr class="odd">
<td><p>start</p></td>
<td><p>0</p></td>
<td><p>Parameter to allow for paging of the result. By default the result will start at 0.</p></td>
</tr>
<tr class="even">
<td><p>size</p></td>
<td><p>10</p></td>
<td><p>Parameter to allow for paging of the result. By default the size will be 10.</p></td>
</tr>
</tbody>
</table>

> **Note**
>
> Bear in mind that the start parameter is used as the offset of the query. For example, to get tasks in three pages of three items each (9 items), we would use:
>
>     GET /runtime/tasks?start=0&size=3
>     GET /runtime/tasks?start=3&size=3
>     GET /runtime/tasks?start=6&size=3

### JSON query variable format

    {
      "name" : "variableName",
      "value" : "variableValue",
      "operation" : "equals",
      "type" : "string"
    }

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>Name of the variable to include in a query. Can be empty in the case where 'equals' is used in some queries to query for resources that have <strong>any variable name</strong> with the given value.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>Yes</p></td>
<td><p>Value of the variable included in the query, should include a correct format for the given type.</p></td>
</tr>
<tr class="odd">
<td><p>operator</p></td>
<td><p>Yes</p></td>
<td><p>Operator to use in query, can have the following values: equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, lessThan, greaterThan, lessThanOrEquals, greaterThanOrEquals and like.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of variable to use. When omitted, the type will be deduced from the value parameter. Any JSON text-values will be considered of type string, JSON booleans of type boolean, JSON numbers of type long or integer depending on the size of the number. We recommended you include an explicit type when in doubt. Types supported out of the box are listed below.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Default query JSON types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as and converted to a java.lang.String.</p></td>
</tr>
<tr class="even">
<td><p>short</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="odd">
<td><p>integer</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as and converted to a java.lang.Long.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as and converted to a java.lang.Double.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as and converted to a java.lang.Boolean.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as and converted to a java.util.Date. The JSON string will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

### Variable representation

When working with variables (execute decision), the REST API uses some common principles and JSON-format for both reading and writing. The JSON representation of a variable looks like this:

    {
      "name" : "variableName",
      "value" : "variableValue",
      "valueUrl" : "http://...",
      "type" : "string"
    }

<table>
<caption>Variable JSON attributes</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>Yes</p></td>
<td><p>Name of the variable.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>No</p></td>
<td><p>Value of the variable. When writing a variable and value is omitted, null will be used as value.</p></td>
</tr>
<tr class="odd">
<td><p>valueUrl</p></td>
<td><p>No</p></td>
<td><p>When reading a variable of type binary or serializable, this attribute will point to the URL from where the raw binary data can be fetched.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of the variable. See table below for additional information on types. When writing a variable and this value is omitted, the type will be deduced from the raw JSON-attribute request type and is limited to either string, double, integer and boolean. We advise you to always include a type to make sure no wrong assumption about the type are made.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Variable Types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as a java.lang.String. Raw JSON-text value is used when writing a variable.</p></td>
</tr>
<tr class="even">
<td><p>integer</p></td>
<td><p>Value is treated as a java.lang.Integer. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>short</p></td>
<td><p>Value is treated as a java.lang.Short. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as a java.lang.Long. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as a java.lang.Double. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as a java.lang.Boolean. When writing, JSON boolean value is used for conversion.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as a java.util.Date. When writing, the JSON text will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

It’s possible to support additional variable-types with a custom JSON representation (either simple value or complex/nested JSON object). By extending the initializeVariableConverters() method on org.flowable.dmn.rest.service.api.DmnRestResponseFactory, you can add additional org.flowable.rest.variable.RestVariableConverter classes to support converting your POJOs to a format suitable for transferring through REST and converting the REST-value back to your POJO. The actual transformation to JSON is done by Jackson.

---

### Docusaurus Docs Oss Introduction (`docs/docusaurus/docs/oss-introduction.md`)

---
id: oss-introduction
title: Introducing Flowable Open Source
sidebar_label: Open Source Details
---

## License

Flowable is distributed under [the Apache V2 license](http://www.apache.org/licenses/LICENSE-2.0.html).

## Download

[<http://www.flowable.org/downloads.html>](http://www.flowable.org/downloads.html)

## Sources

The distribution contains most of the sources as JAR files. The source code for Flowable can be found on
[<https://github.com/flowable/flowable-engine>](https://github.com/flowable/flowable-engine)

## Required software

### JDK 17+

Flowable runs on a JDK higher than or equal to version 17. Go to [Oracle Java SE downloads](http://www.oracle.com/technetwork/java/javase/downloads/index.html) and click on button "Download JDK". There are installation instructions on that page as well. To verify that your installation was successful, run java -version on the command line. That should print the installed version of your JDK.

### Modeling

Flowable offers a free to use Flowable Cloud Design application, which you can use to model CMMN, BPMN, DMN and other model types.
You can register via the Flowable account registration page to get started [Flowable account registration page](https://www.flowable.com/account/open-source).

## Reporting problems

We expect developers to have read [How to ask questions the smart way](http://www.catb.org/~esr/faqs/smart-questions.html) before reporting or asking anything.

After you’ve done that you can post questions, comments or suggestions for enhancements on [the User forum](https://forum.flowable.org) and create issues for bugs in [our Github issue tracker](https://github.com/flowable/flowable-engine/issues).

## Experimental features

Sections marked with **\[EXPERIMENTAL\]** should not be considered stable.

All classes that have .impl. in the package name are internal implementation classes and cannot be considered stable or guaranteed in any way. However, if the User Guide mentions any classes as configuration values, they are supported and can be considered stable.

## Internal implementation classes

In the JAR files, all classes in packages that have .impl. (e.g. org.flowable.engine.impl.db) in their name are implementation classes and should be considered internal use only. No stability guarantees are given on classes or interfaces that are in implementation classes.

## Versioning Strategy

Versions are denoted using a standard triplet of integers: **MAJOR.MINOR.MICRO**. The intention is that **MAJOR** versions are for evolutions of the core engines. **MINOR** versions are for new features and new APIs. **MICRO** versions are for bug fixes and improvements.

In general, Flowable attempts to remain "source compatible" in **MINOR** and **MICRO** releases for all non internal implementation classes. We define "source compatible" to mean an application will continue to build without error and the semantics have remained unchanged. Flowable also attempts to remain "binary compatible" in **MINOR** and **MICRO** releases. We define "binary compatible" to mean that this new version of Flowable can be dropped as a jar replacement into a compiled application and continue to function properly.

In case an API change is introduced in a **MINOR** release, the strategy is that a backwards compatible version is kept in it, annotated with *@Deprecated*. Such deprecated APIs will then be removed two **MINOR** versions later.

---

### Docusaurus Docs Bpmn Ch02 GettingStarted (`docs/docusaurus/docs/bpmn/ch02-GettingStarted.md`)

---
id: ch02-GettingStarted
title: Getting Started
---

## What is Flowable?

Flowable is a light-weight business process engine written in Java. The Flowable process engine allows you to deploy BPMN 2.0 process definitions (an industry XML standard for defining processes),
creating process instances of those process definitions, running queries, accessing active or historical process instances and related data, plus much more. This section will gradually introduce various concepts and
APIs to do that through examples that you can follow on your own development machine.

Flowable is extremely flexible when it comes to adding it to your application/services/architecture. You can *embed* the engine in your application or service by including the Flowable library,
which is available as a JAR. Since it’s a JAR, you can add it easily to any Java environment: Java SE; servlet containers, such as Tomcat or Jetty, Spring; Java EE servers, such as JBoss or WebSphere, and so on.
Alternatively, you can use the Flowable REST API to communicate over HTTP. There are also several Flowable Applications (Flowable Modeler, Flowable Admin, Flowable IDM and Flowable Task) that offer out-of-the-box example UIs for working with processes and tasks.

Common to all the ways of setting up Flowable is the core engine, which can be seen as a collection of services that expose APIs to manage and execute business processes.
The various tutorials below start by introducing how to set up and use this core engine. The sections afterwards build upon the knowledge acquired in the previous sections.

-   The [first section](#building-a-command-line-application) shows how to run Flowable in the simplest way possible: a regular Java main using only Java SE. Many core concepts and APIs will be explained here.

-   The [section on the Flowable REST API](#getting-started-with-the-flowable-rest-api) shows how to run and use the same API through REST.

-   The [section on the Flowable REST App](ch13-Applications.md), will guide you through the basics of using the out-of-the-box example Flowable REST application.

## Flowable and Activiti

Flowable is a fork of Activiti (registered trademark of Alfresco). In all the following sections you’ll notice that the package names, configuration files, and so on, use *flowable*.

## Building a command-line application

### Creating a process engine

In this first tutorial we’re going to build a simple example that shows how to create a Flowable process engine, introduces some core concepts and shows how to work with the API.
The screenshots show Eclipse, but any IDE works. We’ll use Maven to fetch the Flowable dependencies and manage the build, but likewise, any alternative also works (Gradle, Ivy, and so on).

The example we’ll build is a simple *holiday request* process:

-   the *employee* asks for a number of holidays

-   the *manager* either approves or rejects the request

-   we’ll mimic registering the request in some external system and sending out an email to the employee with the result

First, we create a new Maven project through *File → New → Other → Maven Project*



In the next screen, we check '*create a simple project (skip archetype selection)*'



And fill in some *'Group Id'* and *'Artifact id'*:



We now have an empty Maven project, to which we’ll add two dependencies:

-   The Flowable process engine, which will allow us to create a ProcessEngine object and access the Flowable APIs.

-   An in-memory database, H2 in this case, as the Flowable engine needs a database to store execution and historical data while running process instances.
    Note that the H2 dependency includes both the database *and* the driver. If you use another database (for example, PostgresQL, MySQL, and so on), you’ll need to add the specific database driver dependency.

Add the following to your *pom.xml* file:

    <dependencies>
      <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-engine</artifactId>
        <version>7.0.0</version>
      </dependency>
      <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>2.1.214</version>
      </dependency>
    </dependencies>

If the dependent JARs are not automatically retrieved for some reason, you can right-click the project and select '*Maven → Update Project'* to force a manual refresh (but this should not be needed, normally).
In the project, under '*Maven Dependencies*', you should now see the *flowable-engine* and various other (transitive) dependencies.

Create a new Java class and add a regular Java main method:

    package org.flowable;

    public class HolidayRequest {

      public static void main(String[] args) {

      }

    }

The first thing we need to do is to instantiate a **ProcessEngine** instance. This is a thread-safe object that you typically have to instantiate only once in an application.
A *ProcessEngine* is created from a **ProcessEngineConfiguration** instance, which allows you to configure and tweak the settings for the process engine. Often, the *ProcessEngineConfiguration* is created
using a configuration XML file, but (as we do here) you can also create it programmatically. The minimum configuration a *ProcessEngineConfiguration* needs
is a JDBC connection to a database:

    package org.flowable;

    import org.flowable.engine.ProcessEngine;
    import org.flowable.engine.ProcessEngineConfiguration;
    import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;

    public class HolidayRequest {

      public static void main(String[] args) {
        ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
          .setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1")
          .setJdbcUsername("sa")
          .setJdbcPassword("")
          .setJdbcDriver("org.h2.Driver")
          .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

        ProcessEngine processEngine = cfg.buildProcessEngine();
      }

    }

In the code above, on line 10, a *standalone* configuration object is created. The *'standalone'* here refers to the fact that the engine is created and used completely by itself (and not, for example,
in a Spring environment, where you’d use the *SpringProcessEngineConfiguration* class instead). On lines 11 to 14, the JDBC connection parameters to an in-memory H2 database instance are passed.
Important: note that such a database does not survive a JVM restart. If you want your data to be persistent, you’ll need to switch to a persistent database and switch the connection parameters accordingly.
On line 15 we’re setting a flag to *true* to make sure that the database schema is created if it doesn’t already exist in the database pointed to by the JDBC parameters.
Alternatively, Flowable ships with a set of SQL files that can be used to create the database schema with all the tables manually.

The **ProcessEngine** object is then created using this configuration (line 17).

You can now run this. The easiest way in Eclipse is to right-click on the class file and select *Run As → Java Application*:



The application runs without problems, however, no useful information is shown in the console except a message stating that the logging has not been configured properly:



Flowable uses [SLF4J](http://www.slf4j.org/) as its logging framework internally. For this example, we’ll use the log4j logger over SLF4j, so add the following dependencies to the pom.xml file:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>2.0.7</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-reload4j</artifactId>
      <version>2.0.7</version>
    </dependency>

Log4j needs a properties file for configuration. Add a *log4j.properties* file to the *src/main/resources* folder with the following content:

    log4j.rootLogger=DEBUG, CA

    log4j.appender.CA=org.apache.log4j.ConsoleAppender
    log4j.appender.CA.layout=org.apache.log4j.PatternLayout
    log4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n

Rerun the application. You should now see informative logging about the engine booting up and the database schema being created in the database:



We’ve now got a process engine booted up and ready to go. Time to feed it a process!

### Deploying a process definition

The process we’ll build is a very simple holiday request process. The Flowable engine expects processes to be defined in the BPMN 2.0 format, which is an XML standard that is widely accepted in the industry.
In Flowable terminology, we speak about this as a **process definition**. From a *process definition*, many **process instances** can be started. Think of the *process definition* as the blueprint for many executions
of the process. In this particular case, the *process definition* defines the different steps involved in requesting holidays, while one *process instance* matches the request for a holiday by one particular employee.

BPMN 2.0 is stored as XML, but it has a visualization part too: it defines in a standard way how each different step type (a human task, an automatic service call, and so on) is represented and how to connect
these different steps to each other. Through this, the BPMN 2.0 standard allows technical and business people to communicate about business processes in a way that both parties understand.

The process definition we’ll use is the following:



The process should be quite self-explanatory, but for clarity’s sake let’s describe the different bits:

-   We assume the process is started by providing some information, such as the employee name, the amount of holiday requested and a description. Of course, this could be modeled as a separate first step in the process.
    However, by having it as 'input data' for the process, a process instance is only actually created when a real request has been made. In the alternative case, a user could change his mind and cancel before submitting, yet the process instance would now be there.
    In some scenarios this could be valuable information (for example, how many times is a request started, but not finished), depending on the business goal.

-   The circle on the left is called a **start event**. It’s the starting point of a process instance.

-   The first rectangle is a **user task**. This is a step in the process that a human user has to perform. In this case, the manager needs to approve or reject the request.

-   Depending on what the manager decides, the **exclusive gateway** (the diamond shape with the cross) will route the process instance to either the approval or the rejection path.

-   If approved, we have to register the request in some external system, which is followed by a user task again for the original employee that notifies them of the decision.
    This could, of course, be replaced by an email.

-   If rejected, an email is sent to the employee informing them of this.

Typically, such a *process definition* is modeled with a visual modeling tool, such as the Flowable Designer (Eclipse) or the Flowable Modeler (web application).

Here, however, we’re going to write the XML directly to familiarize ourselves with BPMN 2.0 and its concepts.

The BPMN 2.0 XML corresponding to the diagram above is shown below. Note that this is only the 'process part'. If you’d used a graphical modeling tool, the underlying XML file also contains the 'visualization' part that describes the graphical information, such as the coordinates of the various elements of the process definition (all graphical information is contained in the *BPMNDiagram* tag in the XML, which is a child element of the *definitions* tag).

Save the following XML in a file named *holiday-request.bpmn20.xml* in the *src/main/resources* folder.

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
      xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
      xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
      xmlns:flowable="http://flowable.org/bpmn"
      typeLanguage="http://www.w3.org/2001/XMLSchema"
      expressionLanguage="http://www.w3.org/1999/XPath"
      targetNamespace="http://www.flowable.org/processdef">

      <process id="holidayRequest" name="Holiday Request" isExecutable="true">

        <startEvent id="startEvent"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

        <userTask id="approveTask" name="Approve or reject request"/>
        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>

        <exclusiveGateway id="decision"/>
        <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
          <conditionExpression xsi:type="tFormalExpression">
            <![CDATA[
              ${approved}
            ]]>
          </conditionExpression>
        </sequenceFlow>
        <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
          <conditionExpression xsi:type="tFormalExpression">
            <![CDATA[
              ${!approved}
            ]]>
          </conditionExpression>
        </sequenceFlow>

        <serviceTask id="externalSystemCall" name="Enter holidays in external system"
            flowable:class="org.flowable.CallExternalSystemDelegate"/>
        <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>

        <userTask id="holidayApprovedTask" name="Holiday approved"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

        <serviceTask id="sendRejectionMail" name="Send out rejection email"
            flowable:class="org.flowable.SendRejectionMail"/>
        <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>

        <endEvent id="approveEnd"/>

        <endEvent id="rejectEnd"/>

      </process>

    </definitions>

Lines 2 to 11 look a bit daunting, but it’s the same as you’ll see in almost every process definition. It’s kind of *boilerplate* stuff that’s needed to be fully compatible with the BPMN 2.0 standard specification.

Every step (in BPMN 2.0 terminology, **'activity'**) has an *id* attribute that gives it a unique identifier in the XML file. All *activities* can have an optional name too, which increases the readability of the visual diagram, of course.

The *activities* are connected by a **sequence flow**, which is a directed arrow in the visual diagram. When executing a process instance, the execution will flow from the *start event* to the next *activity*, following the *sequence flow*.

The *sequence flows* leaving the *exclusive gateway* (the diamond shape with the X) are clearly special: both have a *condition* defined in the form of an *expression* (see line 25 and 32). When the process instance execution reaches this *gateway*, the *conditions* are evaluated and the first that resolves to *true* is taken. This is what the *exclusive* stands for here: only one is selected. Other types of gateways are, of course, possible if different routing behavior is needed.

The condition written here as an *expression* is of the form *${approved}*, which is a shorthand for *${approved == true}*. The variable 'approved' is called a **process variable**. A *process variable* is a persistent bit of data that is stored together with the process instance and can be used during the lifetime of the process instance. In this case, it does mean that we will have to set this *process variable* at a certain point (when the manager user task is submitted or, in Flowable terminology, *completed*) in the process instance, as it’s not data that is available when the process instance starts.

Now we have the process BPMN 2.0 XML file, we next need to **'deploy'** it to the engine. *Deploying* a process definition means that:

-   the process engine will store the XML file in the database, so it can be retrieved whenever needed

-   the process definition is parsed to an internal, executable object model, so that *process instances* can be started from it.

To *deploy* a process definition to the Flowable engine, the *RepositoryService* is used, which can be retrieved from the *ProcessEngine* object. Using the *RepositoryService*, a new *Deployment* is created by passing the location of the XML file and calling the *deploy()* method to actually execute it:

    RepositoryService repositoryService = processEngine.getRepositoryService();
    Deployment deployment = repositoryService.createDeployment()
      .addClasspathResource("holiday-request.bpmn20.xml")
      .deploy();

We can now verify that the process definition is known to the engine (and learn a bit about the API) by querying it through the API. This is done by creating a new *ProcessDefinitionQuery* object through the *RepositoryService*.

    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
      .deploymentId(deployment.getId())
      .singleResult();
    System.out.println("Found process definition : " + processDefinition.getName());

### Starting a process instance

We now have the process definition *deployed* to the process engine, so *process instances* can be started using this *process definition* as a 'blueprint'.

To start the process instance, we need to provide some initial *process variables*. Typically, you’ll get these through a form that is presented to the user or through a REST API when a process is triggered by something automatic. In this example, we’ll keep it simple and use the java.util.Scanner class to simply input some data on the command line:

    Scanner scanner= new Scanner(System.in);

    System.out.println("Who are you?");
    String employee = scanner.nextLine();

    System.out.println("How many holidays do you want to request?");
    Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());

    System.out.println("Why do you need them?");
    String description = scanner.nextLine();

Next, we can start a *process instance* through the *RuntimeService*. The collected data is passed as a *java.util.Map* instance, where the key is the identifier that will be used to retrieve the variables later on. The process instance is started using a *key*. This *key* matches the *id* attribute that is set in the BPMN 2.0 XML file, in this case *holidayRequest*.

(NOTE: there are many ways you’ll learn later on to start a process instance, beyond using a key)

    <process id="holidayRequest" name="Holiday Request" isExecutable="true">

    RuntimeService runtimeService = processEngine.getRuntimeService();

    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("employee", employee);
    variables.put("nrOfHolidays", nrOfHolidays);
    variables.put("description", description);
    ProcessInstance processInstance =
      runtimeService.startProcessInstanceByKey("holidayRequest", variables);

When the process instance is started, an **execution** is created and put in the start event. From there, this *execution* follows the sequence flow to the user task for the manager approval and executes the user task behavior. This behavior will create a task in the database that can be found using queries later on. A user task is a *wait state* and the engine will stop executing anything further, returning the API call.

### Sidetrack: transactionality

In Flowable, database transactions play a crucial role to guarantee data consistency and solve concurrency problems. When you make a Flowable API call, by default, everything is synchronous and part of the same transaction. Meaning, when the method call returns, a transaction will be started and committed.

When a process instance is started, there will be **one database transaction** from the start of the process instance to the next *wait state*. In this example, this is the first user task. When the engine reaches this user task, the state is persisted to the database and the transaction is committed and the API call returns.

In Flowable, when continuing a process instance, there will always be one database transaction going from the previous *wait state* to the next *wait state*. Once persisted, the data can be in the database for a long time, even years if it has to be, until an API call is executed that takes the process instance further. Note that no computing or memory resources are consumed when the process instance is in such a wait state, waiting for the next API call.

In the example here, when the first user task is completed, one database transaction will be used to go from the user task through the exclusive gateway (the automatic logic) until the second user task. Or straight to the end with the other path.

### Querying and completing tasks

In a more realistic application, there will be a user interface where the employees and the managers can log in and see their task lists. With these, they can inspect the process instance data that is stored as *process variables* and decide what they want to do with the task. In this example, we will mimic task lists by executing the API calls that normally would be behind a service call that drives a UI.

We haven’t yet configured the assignment for the user tasks. We want the first task to go the 'managers' group and the second user task to be assigned to the original requester of the holiday. To do this, add the *candidateGroups* attribute to the first task:

    <userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="managers"/>

and the *assignee* attribute to the second task as shown below. Note that we’re not using a static value like the 'managers' value above, but a dynamic assignment based on a process variable that we’ve passed when the process instance was started:

    <userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/>

To get the actual task list, we create a *TaskQuery* through the *TaskService* and we configure the query to only return the tasks for the 'managers' group:

    TaskService taskService = processEngine.getTaskService();
    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
    System.out.println("You have " + tasks.size() + " tasks:");
    for (int i=0; i<tasks.size(); i++) {
      System.out.println((i+1) + ") " + tasks.get(i).getName());
    }

Using the task identifier, we can now get the specific process instance variables and show on the screen the actual request:

    System.out.println("Which task would you like to complete?");
    int taskIndex = Integer.valueOf(scanner.nextLine());
    Task task = tasks.get(taskIndex - 1);
    Map<String, Object> processVariables = taskService.getVariables(task.getId());
    System.out.println(processVariables.get("employee") + " wants " +
        processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");

Which, if you run this, should look something like this:



The manager can now **complete the task**. In reality, this often means that a form is submitted by the user. The data from the form is then passed as *process
variables*. Here, we’ll mimic this by passing a map with the 'approved' variable (the name is important, as it’s used later on in the conditions of the sequence flow!) when the task is completed:

    boolean approved = scanner.nextLine().toLowerCase().equals("y");
    variables = new HashMap<String, Object>();
    variables.put("approved", approved);
    taskService.complete(task.getId(), variables);

The task is now completed and one of the two paths leaving the exclusive gateway is selected based on the 'approved' process variable.

### Writing a JavaDelegate

There is a last piece of the puzzle still missing: we haven’t implemented the automatic logic that will get executed when the request is approved. In the BPMN 2.0 XML this is a **service task** and it looked above like:

    <serviceTask id="externalSystemCall" name="Enter holidays in external system"
        flowable:class="org.flowable.CallExternalSystemDelegate"/>

In reality, this logic could be anything, ranging from calling a service with HTTP REST, to executing some legacy code calls to a system the organization has
been using for decades. We won’t implement the actual logic here but simply log the *processing*.

Create a new class (*File → New → Class* in Eclipse), fill in *org.flowable* as package name and *CallExternalSystemDelegate* as class name. Make that class implement the *org.flowable.engine.delegate.JavaDelegate* interface and implement the *execute* method:

    package org.flowable;

    import org.flowable.engine.delegate.DelegateExecution;
    import org.flowable.engine.delegate.JavaDelegate;

    public class CallExternalSystemDelegate implements JavaDelegate {

        public void execute(DelegateExecution execution) {
            System.out.println("Calling the external system for employee "
                + execution.getVariable("employee"));
        }

    }

When the *execution* arrives at the *service task*, the class that is referenced in the BPMN 2.0 XML is instantiated and called.

When running the example now, the logging message is shown, demonstrating the custom logic is indeed executed:



### Working with historical data

One of the many reasons for choosing to use a process engine like Flowable is because it automatically stores **audit data** or **historical data** for all the process instances. This data allows the creation of rich reports that give insights into how the organization works, where the bottlenecks are, etc.

For example, suppose we want to show the duration of the process instance that we’ve been executing so far. To do this, we get the *HistoryService* from the *ProcessEngine* and create a query for *historical activities*. In the snippet below you can see we add some additional filtering:

-   only the activities for one particular process instance

-   only the activities that have finished

The results are also sorted by end time, meaning that we’ll get them in execution order.

    HistoryService historyService = processEngine.getHistoryService();
    List<HistoricActivityInstance> activities =
      historyService.createHistoricActivityInstanceQuery()
       .processInstanceId(processInstance.getId())
       .finished()
       .orderByHistoricActivityInstanceEndTime().asc()
       .list();

    for (HistoricActivityInstance activity : activities) {
      System.out.println(activity.getActivityId() + " took "
        + activity.getDurationInMillis() + " milliseconds");
    }

Running the example again, we now see something like this in the console:

    startEvent took 1 milliseconds
    approveTask took 2638 milliseconds
    decision took 3 milliseconds
    externalSystemCall took 1 milliseconds

### Conclusion

This tutorial introduced various Flowable and BPMN 2.0 concepts and terminology, while also demonstrating how to use the Flowable API programmatically.

Of course, this is just the start of the journey. The following sections will dive more deeply into the many options and features that the Flowable engine supports. Other sections go into the various ways the Flowable engine can be set up and used, and describe in detail all the BPMN 2.0 constructs that are possible.

## Getting started with the Flowable REST API

This section shows the same example as the [previous section](#building-a-command-line-application): deploying a process definition, starting a process instance, getting a task list and completing a task. If you haven’t read that section, it might be good to skim through it to get an idea of what is done there.

This time, the Flowable REST API is used rather than the Java API. You’ll soon notice that the REST API closely matches the Java API, and knowing one automatically means that you can find your way around the other.

To get a full, detailed overview of the Flowable REST API, check out the [REST API chapter](bpmn/ch14-REST.md#rest-api).

### Setting up the REST application

When you download the .zip file from the flowable.org website, the REST application can be found in the *wars* folder. You’ll need a servlet container, such as [Tomcat](http://tomcat.apache.org//), [Jetty](http://www.eclipse.org/jetty//), and so on, to run the WAR file.

>Note: The flowable-rest.war is based on Spring Boot, which means that it supports the Tomcat / Jetty servlet containers supported by Spring Boot.

When using Tomcat the steps are as follows:

-   Download and unzip the latest and greatest Tomcat zip file (choose the 'Core' distribution from the Tomcat website).

-   Copy the flowable-rest.war file from the *wars* folder of the unzipped Flowable distribution to the *webapps* folder of the unzipped Tomcat folder.

-   On the command line, go to the *bin* folder of the Tomcat folder.

-   Execute '*./catalina run*' to boot up the Tomcat server.

During the server boot up, you’ll notice some Flowable logging messages passing by. At the end, a message like '*INFO \[main\] org.apache.catalina.startup.Catalina.start Server startup in xyz ms*' indicates that the server is ready to receive requests. Note that by default an in-memory H2 database instance is used, which means that data won’t survive a server restart.

In the following sections, we’ll use cURL to demonstrate the various REST calls. All REST calls are by default protected with *basic authentication*. The user 'rest-admin' with password 'test' is used in all calls.

After boot up, verify the application is running correctly by executing

    curl --user rest-admin:test http://localhost:8080/flowable-rest/service/management/engine

If you get back a proper json response, the REST API is up and running.

### Deploying a process definition

The first step is to deploy a process definition. With the REST API, this is done by uploading a .bpmn20.xml file (or .zip file for multiple process definitions) as 'multipart/formdata':

    curl --user rest-admin:test  -X POST -F "file=@holiday-request.bpmn20.xml" http://localhost:8080/flowable-rest/service/repository/deployments

To verify that the process definition is deployed correctly, the list of process definitions can be requested:

    curl --user rest-admin:test http://localhost:8080/flowable-rest/service/repository/process-definitions

which returns a list of all process definitions currently deployed to the engine.

### Start a process instance

Starting a process instance through the REST API is similar to doing the same through the Java API: a *key* is provided to identify the process definition to use along with a map of initial process variables:

    curl --user rest-admin:test -H "Content-Type: application/json" -X POST -d '{ "processDefinitionKey":"holidayRequest", "variables": [ { "name":"employee", "value": "John Doe" }, { "name":"nrOfHolidays", "value": 7 }]}' http://localhost:8080/flowable-rest/service/runtime/process-instances

which returns something like

    {"id":"43","url":"http://localhost:8080/flowable-rest/service/runtime/process-instances/43","businessKey":null,"suspended":false,"ended":false,"processDefinitionId":"holidayRequest:1:42","processDefinitionUrl":"http://localhost:8080/flowable-rest/service/repository/process-definitions/holidayRequest:1:42","activityId":null,"variables":[],"tenantId":"","completed":false}

### Task list and completing a task

When the process instance is started, the first task is assigned to the 'managers' group. To get all tasks for this group, a task query can be done through the REST API:

    curl --user rest-admin:test -H "Content-Type: application/json" -X POST -d '{ "candidateGroup" : "managers" }' http://localhost:8080/flowable-rest/service/query/tasks

which returns a list of all tasks for the 'managers' group

Such a task can now be completed using:

    curl --user rest-admin:test -H "Content-Type: application/json" -X POST -d '{ "action" : "complete", "variables" : [ { "name" : "approved", "value" : true} ]  }' http://localhost:8080/flowable-rest/service/runtime/tasks/25

However, you most likely will get an error like:

    {"message":"Internal server error","exception":"couldn't instantiate class org.flowable.CallExternalSystemDelegate"}

This means that the engine couldn’t find the *CallExternalSystemDelegate* class that is referenced in the service task. To solve this, the class needs to be put on the classpath of the application (which will require a restart). Create the class as described in [this section](bpmn/ch02-GettingStarted.md#writing-a-javadelegate), package it up as a JAR and put it in the *WEB-INF/lib* folder of the flowable-rest folder under the *webapps* folder of Tomcat.

---

### Docusaurus Docs Bpmn Ch03 Configuration (`docs/docusaurus/docs/bpmn/ch03-Configuration.md`)

---
id: ch03-Configuration
title: Configuration
---

## Creating a ProcessEngine

The Flowable process engine is configured through an XML file called flowable.cfg.xml. Note that this is **not** applicable if you’re using [the Spring style of building a process engine](bpmn/ch05-Spring.md#spring-integration).

The easiest way to obtain a ProcessEngine is to use the org.flowable.engine.ProcessEngines class:

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine()

This will look for a flowable.cfg.xml file on the classpath and construct an engine based on the configuration in that file. The following snippet shows an example configuration. The following sections will give a detailed overview of the configuration properties.

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="jdbcDriver" value="org.h2.Driver" />
        <property name="jdbcUsername" value="sa" />
        <property name="jdbcPassword" value="" />

        <property name="databaseSchemaUpdate" value="true" />

        <property name="asyncExecutorActivate" value="false" />

        <property name="mailServerHost" value="mail.my-corp.com" />
        <property name="mailServerPort" value="5025" />
      </bean>

    </beans>

Note that the configuration XML is in fact a Spring configuration. **This does not mean that Flowable can only be used in a Spring environment!** We are simply leveraging the parsing and dependency injection capabilities of Spring internally for building up the engine.

The ProcessEngineConfiguration object can also be created programmatically using the configuration file. It is also possible to use a different bean id (for example, see line 3).

    ProcessEngineConfiguration.
      createProcessEngineConfigurationFromResourceDefault();
      createProcessEngineConfigurationFromResource(String resource);
      createProcessEngineConfigurationFromResource(String resource, String beanName);
      createProcessEngineConfigurationFromInputStream(InputStream inputStream);
      createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName);

It is also possible not to use a configuration file, and create a configuration based on
defaults (see [the different supported classes](#configurationClasses) for more information).

    ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
    ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration();

All these ProcessEngineConfiguration.createXXX() methods return a ProcessEngineConfiguration that can be tweaked further if needed. After calling the buildProcessEngine() operation, a ProcessEngine is created:

    ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
      .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
      .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
      .setAsyncExecutorActivate(false)
      .buildProcessEngine();
      
## ProcessEngineConfiguration bean

The flowable.cfg.xml must contain a bean that has the id 'processEngineConfiguration'.

     <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">

<a name="configurationClasses"/>
This bean is then used to construct the ProcessEngine. There are multiple classes available that can be used to define the processEngineConfiguration. These classes represent different environments, and set defaults accordingly. It’s best practice to select the class that best matches your environment, to minimize the number of properties needed to configure the engine. The following classes are currently available:

-   **org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration**: the process engine is used in a standalone way. Flowable will take care of all transactions. By default, the database will only be checked when the engine boots (and an exception is thrown if there is no Flowable schema or the schema version is incorrect).

-   **org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration**: this is a convenience class for unit testing purposes. Flowable will take care of all transactions. An H2 in-memory database is used by default. The database will be created and dropped when the engine boots and shuts down. When using this, no additional configuration is probably needed (except when using, for example, the job executor or mail capabilities).

-   **org.flowable.spring.SpringProcessEngineConfiguration**: To be used when the process engine is used in a Spring environment. See [the Spring integration section](bpmn/ch05-Spring.md#spring-integration) for more information.

-   **org.flowable.engine.impl.cfg.JtaProcessEngineConfiguration**: To be used when the engine runs in standalone mode, with JTA transactions.

## Database configuration

There are two ways to configure the database that the Flowable engine will use. The first option is to define the JDBC properties of the database:

-   **jdbcUrl**: JDBC URL of the database.

-   **jdbcDriver**: implementation of the driver for the specific database type.

-   **jdbcUsername**: username to connect to the database.

-   **jdbcPassword**: password to connect to the database.

The data source that is constructed based on the provided JDBC properties will have the default [MyBatis](http://www.mybatis.org/) connection pool settings. The following attributes can optionally be set to tweak that connection pool (taken from the MyBatis documentation):

-   **jdbcMaxActiveConnections**: The number of active connections that the connection pool at maximum at any time can contain. Default is 10.

-   **jdbcMaxIdleConnections**: The number of idle connections that the connection pool at maximum at any time can contain.

-   **jdbcMaxCheckoutTime**: The amount of time in milliseconds a connection can be 'checked out' from the connection pool before it is forcefully returned. Default is 20000 (20 seconds).

-   **jdbcMaxWaitTime**: This is a low level setting that gives the pool a chance to print a log status and re-attempt the acquisition of a connection in the case that it is taking unusually long (to avoid failing silently forever if the pool is misconfigured) Default is 20000 (20 seconds).

Example database configuration:

    <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />

Our benchmarks have shown that the MyBatis connection pool is not the most efficient or resilient when dealing with a lot of concurrent requests. As such, it is advised to use a javax.sql.DataSource implementation and inject it into the process engine configuration (For example HikariCP, Tomcat JDBC Connection Pool, etc.):

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/flowable" />
      <property name="username" value="flowable" />
      <property name="password" value="flowable" />
      <property name="defaultAutoCommit" value="false" />
    </bean>

    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">

      <property name="dataSource" ref="dataSource" />
      ...

Note that Flowable does not ship with a library that allows you to define such a data source. So you need to make sure that the libraries are on your classpath.

The following properties can be set, regardless of whether you are using the JDBC or data source approach:

-   **databaseType**: it’s normally not necessary to specify this property, as it is automatically detected from the database connection metadata. Should only be specified when automatic detection fails. Possible values: {h2, mysql, oracle, postgres, mssql, db2}. This setting will determine which create/drop scripts and queries will be used. See [the 'supported databases' section](bpmn/ch03-Configuration.md#supported-databases) for an overview of which types are supported.

-   **databaseSchemaUpdate**: sets the strategy to handle the database schema on process engine boot and shutdown.

    -   false (default): Checks the version of the DB schema against the library when the process engine is being created and throws an exception if the versions don’t match.

    -   true: Upon building the process engine, a check is performed and an update of the schema is performed if it is necessary. If the schema doesn’t exist, it is created.

    -   create-drop: Creates the schema when the process engine is being created and drops the schema when the process engine is being closed.

## JNDI Datasource Configuration

By default, the database configuration for Flowable is contained within the db.properties files in the WEB-INF/classes of each web application. This isn’t always ideal because it
requires users to either modify the db.properties in the Flowable source and recompile the WAR file, or explode the WAR and modify the db.properties on every deployment.

By using JNDI (Java Naming and Directory Interface) to obtain the database connection, the connection is fully managed by the Servlet Container and the configuration can be managed outside the WAR deployment. This also allows more control over the connection parameters than what is provided by the db.properties file.

### Configuration

Configuration of the JNDI data source will differ depending on what servlet container application you are using. The instructions below will work for Tomcat, but for other container applications, please refer to the documentation for your container app.

If using Tomcat, the JNDI resource is configured within $CATALINA\_BASE/conf/\[enginename\]/\[hostname\]/\[warname\].xml (for the Flowable UI this will usually be $CATALINA\_BASE/conf/Catalina/localhost/flowable-app.xml). The default context is copied from the Flowable WAR file when the application is first deployed, so if it already exists, you will need to replace it. To change the JNDI resource so that the application connects to MySQL instead of H2, for example, change the file to the following:

    <?xml version="1.0" encoding="UTF-8"?>
        <Context antiJARLocking="true" path="/flowable-app">
            <Resource auth="Container"
                name="jdbc/flowableDB"
                type="javax.sql.DataSource"
                description="JDBC DataSource"
                url="jdbc:mysql://localhost:3306/flowable"
                driverClassName="com.mysql.jdbc.Driver"
                username="sa"
                password=""
                defaultAutoCommit="false"
                initialSize="5"
                maxWait="5000"
                maxActive="120"
                maxIdle="5"/>
            </Context>

### JNDI properties

To configure a JNDI data source, use following properties in the properties file for the Flowable UI:

-   spring.datasource.jndi-name=: the JNDI name of the data source.

-   datasource.jndi.resourceRef: Set whether the lookup occurs in a J2EE container, for example, the prefix "java:comp/env/" needs to be added if the JNDI name doesn’t already contain it. Default is "true".

### Custom properties

System properties can also be used in the flowable.cfg.xml by using them in the format `${propertyName:defaultValue}`.

    <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
    <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
    <property name="jdbcUsername" value="${jdbc.username:sa}" />
    <property name="jdbcPassword" value="${jdbc.password:}" />

Using this configuration if the property `jdbc.url` is available then it would be used for the `jdbcUrl` of the `ProcessEngineConfiguration`.
Otherwise the value after the first `:` would be used.

It is also possible to define locations from where properties can be picked up from the system by using a bean of type org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.

Example configuration with custom location for properties

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/opt/conf/flowable.properties" />
      </bean>

      <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
        <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
        <property name="jdbcUsername" value="${jdbc.username:sa}" />
        <property name="jdbcPassword" value="${jdbc.password:}" />

        <property name="databaseSchemaUpdate" value="true" />

        <property name="asyncExecutorActivate" value="false" />

        <property name="mailServerHost" value="mail.my-corp.com" />
        <property name="mailServerPort" value="5025" />
      </bean>

    </beans>

With this configuration the properties would be first looked up in the /opt/conf/flowable.properties file.

## Supported databases

Listed below are the types (case sensitive!) that Flowable uses to refer to databases.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Flowable database type</th>
<th>Example JDBC URL</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>h2</p></td>
<td><p>jdbc:h2:tcp://localhost/flowable</p></td>
<td><p>Default configured database</p></td>
</tr>
<tr class="even">
<td><p>mysql</p></td>
<td><p>jdbc:mysql://localhost:3306/flowable?autoReconnect=true</p></td>
<td><p>Tested using mysql-connector-java database driver</p></td>
</tr>
<tr class="odd">
<td><p>oracle</p></td>
<td><p>jdbc:oracle:thin:@localhost:1521:xe</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>postgres</p></td>
<td><p>jdbc:postgresql://localhost:5432/flowable</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>db2</p></td>
<td><p>jdbc:db2://localhost:50000/flowable</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>mssql</p></td>
<td><p>jdbc:sqlserver://localhost:1433;databaseName=flowable (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) <em>OR</em> jdbc:jtds:sqlserver://localhost:1433/flowable (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)</p></td>
<td><p>Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver</p></td>
</tr>
</tbody>
</table>

## Creating the database tables

The easiest way to create the database tables for your database is to:

-   Add the flowable-engine JARs to your classpath

-   Add a suitable database driver

-   Add a Flowable configuration file (*flowable.cfg.xml*) to your classpath, pointing to your database (see [database configuration section](bpmn/ch03-Configuration.md#database-configuration))

-   Execute the main method of the *DbSchemaCreate* class

However, often only database administrators can execute DDL statements on a database. On a production system, this is also the wisest of choices. The SQL DDL statements can be found on the Flowable downloads page or inside the Flowable distribution folder, in the database subdirectory. The scripts are also in the engine JAR (*flowable-engine-x.jar*), in the package *org/flowable/db/create* (the *drop* folder contains the drop statements). The SQL files are of the form

    flowable.{db}.{create|drop}.{type}.sql

Where *db* is any of the [supported databases](bpmn/ch03-Configuration.md#supported-databases) and *type* is:

-   **engine:** the tables needed for engine execution. Required.

-   **history:** the tables that contain the history and audit information. Optional: not needed when history level is set to *none*. Note that this will also disable some features (such as commenting on tasks) which store the data in the history database.

**Note for MySQL users:** MySQL versions lower than 5.6.4 have no support for timestamps or dates with millisecond precision. To make things even worse, some versions will throw an exception when trying to create such a column, but other versions don’t. When doing auto-creation/upgrade, the engine will change the DDL when executing it. When using the DDL file approach, both a regular version and a special file with *mysql55* in it are available (this applies on anything lower than 5.6.4). This latter file will have column types with no millisecond precision.

Concretely, the following applies for MySQL versions:

-   **&lt;5.6:** No millisecond precision available. DDL files available (look for files containing *mysql55*). Auto creation/update will work out of the box.

-   **5.6.0 - 5.6.3:** No millisecond precision available. Auto creation/update will NOT work. It is advised to upgrade to a newer database version anyway. DDL files for *mysql 5.5* could be used if really needed.

-   **5.6.4+:** Millisecond precision available. DDL files available (default file containing *mysql*). Auto creation/update works out of the box.

Do note that in the case of upgrading the MySQL database later on and the Flowable tables are already created/upgraded, the column type change will have to be done manually!

## Database table names explained

The database names of Flowable all start with **ACT\_**. The second part is a two-character identification of the use case of the table. This use case will also roughly match the service API.

-   **ACT\_RE\_**\*: 'RE' stands for repository. Tables with this prefix contain 'static' information such as process definitions and process resources (images, rules, etc.).

-   **ACT\_RU\_**\*: 'RU' stands for runtime. These are the runtime tables that contain the runtime data of process instances, user tasks, variables, jobs, and so on. Flowable only stores the runtime data during process instance execution and removes the records when a process instance ends. This keeps the runtime tables small and fast.

-   **ACT\_HI\_**\*: 'HI' stands for history. These are the tables that contain historic data, such as past process instances, variables, tasks, and so on.

-   **ACT\_GE\_**\*: general data, which is used for various use cases.

## Database upgrade

Make sure you make a backup of your database (using your database backup capabilities) before you run an upgrade.

By default, a version check will be performed each time a process engine is created. This typically happens once at boot time of your application or of the Flowable webapps. If the Flowable library notices a difference between the library version and the version of the Flowable database tables, then an exception is thrown.

To upgrade, you have to start by putting the following configuration property in your flowable.cfg.xml configuration file:

    <beans >

      <bean id="processEngineConfiguration"
          class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        
        <property name="databaseSchemaUpdate" value="true" />
        
      </bean>

    </beans>

**Also, include a suitable database driver for your database to the classpath.** Upgrade the Flowable libraries in your application. Or start up a new version of Flowable and point it to a database that contains data from an older version. With databaseSchemaUpdate set to true, Flowable will automatically upgrade the DB schema to the newest version the first time when it notices that libraries and DB schema are out of sync.

**As an alternative, you can also run the upgrade DDL statements.** It’s also possible to run the upgrade database scripts available on the Flowable downloads page.

## Job Executor (from version 6.0.0 onwards)

The async executor of Flowable v5 is the only available job executor in Flowable V6, as it is a more performant and more database friendly way of executing asynchronous jobs in the Flowable engine.
The old job executor of Flowable 5 is no longer available in V6. More information can be found in the advanced section of the user guide.

Additionally, if running under Java EE 7, JSR-236 compliant ManagedAsyncJobExecutor can be used for letting the container manage the threads. In order to enable them, the thread factory should be passed in the configuration as follows:

    <bean id="threadFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiName" value="java:jboss/ee/concurrency/factory/default" />
    </bean>

    <bean id="customJobExecutor" class="org.flowable.engine.impl.jobexecutor.ManagedAsyncJobExecutor">
       
       <property name="threadFactory" ref="threadFactory" />
       
    </bean>

The managed implementations fall back to their default counterparts if the thread factory is not specified.

## Job executor activation

The AsyncExecutor is a component that manages a thread pool to fire timers and other asynchronous tasks.

By default, the AsyncExecutor is not activated and not started. With the following configuration the async executor can be started together with the Flowable Engine.

    <property name="asyncExecutorActivate" value="true" />

The property asyncExecutorActivate instructs the Flowable engine to start the Async executor at startup.

## Mail server configuration

Configuring a mail server is optional. Flowable supports sending e-mails in business processes. To actually send an e-mail, a valid SMTP mail server configuration is required. See the [e-mail task](bpmn/ch07b-BPMN-Constructs.md#mail-server-configuration) for the configuration options.

## History configuration

Customizing the configuration of history storage is optional. This allows you to tweak settings that influence the [history capabilities](bpmn/ch10-History.md#history) of the engine. See [history configuration](bpmn/ch10-History.md#history-configuration) for more details.

    <property name="history" value="audit" />

## Exposing configuration beans in expressions and scripts

By default, all beans that you specify in the flowable.cfg.xml configuration or in your own Spring configuration file are available to expressions and scripts. If you want to limit the visibility of beans in your configuration file, you can configure a property called beans in your process engine configuration. The beans property in ProcessEngineConfiguration is a map. When you specify that property, only beans specified in that map will be visible to expressions and scripts. The exposed beans will be exposed with the names as you specify in the map.

## Deployment cache configuration

All process definitions are cached (after they’re parsed) to avoid hitting the database every time a process definition is needed and because process definition data doesn’t change. By default, there is no limit on this cache. To limit the process definition cache, add following property:

    <property name="processDefinitionCacheLimit" value="10" />

Setting this property will swap the default hashmap cache with a LRU cache that has the provided hard limit. Of course, the 'best' value for this property depends on the total amount of process definitions stored and the number of process definitions actually used at runtime by all the runtime process instances.

You can also inject your own cache implementation. This must be a bean that implements the org.flowable.engine.impl.persistence.deploy.DeploymentCache interface:

    <property name="processDefinitionCache">
      <bean class="org.flowable.MyCache" />
    </property>

There is a similar property called knowledgeBaseCacheLimit and knowledgeBaseCache for configuring the rules cache. This is only needed when you use the rules task in your processes.

## Logging

All logging (flowable, spring, mybatis, …​) is routed through SLF4J and allows for selecting the logging-implementation of your choice.

**By default no SFL4J-binding JAR is present in the flowable-engine dependencies, this should be added in your project in order to use the logging framework of your choice.** If no implementation JAR is added, SLF4J will use a NOP-logger, not logging anything at all, other than a warning that nothing will be logged. For more info on these bindings [<http://www.slf4j.org/codes.html#StaticLoggerBinder>](http://www.slf4j.org/codes.html#StaticLoggerBinder).

With Maven, add for example a dependency like this (here using log4j), note that you still need to add a version:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-reload4j</artifactId>
    </dependency>

The flowable-rest webapp is configured to use Log4j-binding. Log4j is also used when running the tests for all the flowable-\* modules.

**Important note when using a container with commons-logging in the classpath:** In order to route the spring-logging through SLF4J, a bridge is used (see [<http://www.slf4j.org/legacy.html#jclOverSLF4J>](http://www.slf4j.org/legacy.html#jclOverSLF4J)). If your container provides a commons-logging implementation, please follow directions on this page: [<http://www.slf4j.org/codes.html#release>](http://www.slf4j.org/codes.html#release) to ensure stability.

Example when using Maven (version omitted):

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
    </dependency>

## Mapped Diagnostic Contexts

Flowable supports the Mapped Diagnostic Contexts feature of SLF4j. This basic information is passed to the underlying logger along with what is going to be logged:

-   processDefinition Id as mdcProcessDefinitionID

-   processInstance Id as mdcProcessInstanceID

-   execution Id as mdcExecutionId

None of this information is logged by default. The logger can be configured to show them in your desired format, extra to the usual logged messages. For example in
Log4j the following sample layout definition causes the logger to show the above mentioned information:

    log4j.appender.consoleAppender.layout.ConversionPattern=ProcessDefinitionId=%X{mdcProcessDefinitionID}
    executionId=%X{mdcExecutionId} mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %m%n

This is useful when the logs contain information that needs to checked in real time, by means of a log analyzer, for example.

## Event handlers

The event mechanism in the Flowable engine allows you to get notified when various events occur within the engine. Take a look at [all supported event types](bpmn/ch03-Configuration.md#supported-event-types) for an overview of the events available.

It’s possible to register a listener for certain types of events as opposed to getting notified when any type of event is dispatched. You can either add engine-wide event listeners [through the configuration](bpmn/ch03-Configuration.md#configuration-and-setup), add engine-wide event listeners [at runtime using the API](bpmn/ch03-Configuration.md#adding-listeners-at-runtime) or add event-listeners to [specific process definitions in the BPMN XML](bpmn/ch03-Configuration.md#adding-listeners-to-process-definitions).

All events dispatched are a subtype of org.flowable.engine.common.api.delegate.event.FlowableEvent. The event exposes (if available) the type, executionId, processInstanceId and processDefinitionId. Certain events contain additional context related to the event that occurred, more information about additional payloads can be found in the list of [all supported event types](bpmn/ch03-Configuration.md#supported-event-types).

### Event listener implementation

The only requirement for an event-listener is to implement org.flowable.common.engine.api.delegate.event.FlowableEventListener. Below is an example implementation of a listener, which outputs all events received to the standard-out, with exception of events related to job-execution:

    public class MyEventListener implements FlowableEventListener {

      @Override
      public void onEvent(FlowableEvent event) {

        if(event.getType() == FlowableEngineEventType.JOB_EXECUTION_SUCCESS) {
          System.out.println("A job well done!");
        } else if (event.getType() == FlowableEngineEventType.JOB_EXECUTION_FAILURE) {
          System.out.println("A job has failed...");
        } else {
          System.out.println("Event received: " + event.getType());
        }
      }

      @Override
      public boolean isFailOnException() {
        // The logic in the onEvent method of this listener is not critical, exceptions
        // can be ignored if logging fails...
        return false;
      }

      @Override
      public boolean isFireOnTransactionLifecycleEvent() {
        return false;
      }

      @Override
      public String getOnTransaction() {
        return null;
      }
    }

The isFailOnException() method determines the behavior when the onEvent(..) method throws an exception when an event is dispatched. When false is returned, the exception is ignored. When true is returned, the exception is not ignored and bubbles up, effectively failing the current ongoing command. If the event was part of an API-call (or any other transactional operation, for example, job-execution), the transaction will be rolled back. If the behavior in the event-listener is not business-critical, it’s recommended to return false.

The isFireOnTransactionLifecycleEvent() method determines whether this event listener fires immediately when the event occurs or on a
transaction lifecycle event determined by getOnTransaction() method.
Supported values of the transaction life cycle event are: COMMITTED, ROLLED\_BACK, COMMITTING, ROLLINGBACK.

There are a few base implementations provided by Flowable to facilitate common use cases of event-listeners. These can be used as base-class or as an example listener implementation:

-   **org.flowable.engine.delegate.event.BaseEntityEventListener**: An event-listener base-class that can be used to listen for entity-related events for a specific type of entity or for all entities. It hides away the type-checking and offers 4 methods that should be overridden: onCreate(..), onUpdate(..) and onDelete(..) when an entity is created, updated or deleted. For all other entity-related events, the onEntityEvent(..) is called.

### Configuration and setup

If an event-listener is configured in the process engine configuration, it will be active when the process engine starts and will remain active after subsequent reboots of the engine.

The property eventListeners expects a list of org.flowable.common.engine.api.delegate.event.FlowableEventListener instances. As usual, you can either declare an inline bean definition or use a ref to an existing bean instead. The snippet below adds an event-listener to the configuration that is notified when any event is dispatched, regardless of its type:

    <bean id="processEngineConfiguration"
        class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        ...
        <property name="eventListeners">
          <list>
             <bean class="org.flowable.engine.example.MyEventListener" />
          </list>
        </property>
    </bean>

To get notified when certain types of events get dispatched, use the typedEventListeners property, which expects a map. The key of a map-entry is a comma-separated list of event-names (or a single event-name). The value of a map-entry is a list of org.flowable.common.engine.api.delegate.event.FlowableEventListener instances. The snippet below adds an event-listener to the configuration, that is notified when a job execution was successful or failed:

    <bean id="processEngineConfiguration"
        class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        ...
        <property name="typedEventListeners">
          <map>
            <entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
              <list>
                <bean class="org.flowable.engine.example.MyJobEventListener" />
              </list>
            </entry>
          </map>
        </property>
    </bean>

The order of dispatching events is determined by the order in which the listeners were added. First, all normal event-listeners are called (eventListeners property) in the order they are defined in the list. After that, all typed event listeners (typedEventListeners properties) are called, if an event of the right type is dispatched.

### Adding listeners at runtime

It’s possible to add and remove additional event-listeners to the engine by using the API (RuntimeService):

    /**
     * Adds an event-listener which will be notified of ALL events by the dispatcher.
     * @param listenerToAdd the listener to add
     */
    void addEventListener(FlowableEventListener listenerToAdd);

    /**
     * Adds an event-listener which will only be notified when an event occurs,
     * which type is in the given types.
     * @param listenerToAdd the listener to add
     * @param types types of events the listener should be notified for
     */
    void addEventListener(FlowableEventListener listenerToAdd, FlowableEventType... types);

    /**
     * Removes the given listener from this dispatcher. The listener will no longer be notified,
     * regardless of the type(s) it was registered for in the first place.
     * @param listenerToRemove listener to remove
     */
     void removeEventListener(FlowableEventListener listenerToRemove);

Please note that the listeners added at runtime **are not retained when the engine is rebooted.**

### Adding listeners to process definitions

It’s possible to add listeners to a specific process-definition. The listeners will only be called for events related to the process definition and to all events related to process instances that are started with that specific process definition. The listener implementations can be defined using a fully qualified classname, an expression that resolves to a bean that implements the listener interface or can be configured to throw a message/signal/error BPMN event.

#### Listeners executing user-defined logic

The snippet below adds 2 listeners to a process-definition. The first listener will receive events of any type, with a listener implementation based on a fully-qualified class name. The second listener is only notified when a job is successfully executed or when it failed, using a listener that has been defined in the beans property of the process engine configuration.

    <process id="testEventListeners">
      <extensionElements>
        <flowable:eventListener class="org.flowable.engine.test.MyEventListener" />
        <flowable:eventListener delegateExpression="${testEventListener}" events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />
      </extensionElements>

      ...

    </process>

For events related to entities, it’s also possible to add listeners to a process-definition that get only notified when entity-events occur for a certain entity type. The snippet below shows how this can be achieved. It can be used along for ALL entity-events (first example) or for specific event types only (second example).

    <process id="testEventListeners">
      <extensionElements>
        <flowable:eventListener class="org.flowable.engine.test.MyEventListener" entityType="task" />
        <flowable:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
      </extensionElements>

      ...

    </process>

Supported values for the entityType are: attachment, comment, execution, identity-link, job, process-instance, process-definition, task.

#### Listeners throwing BPMN events

Another way of handling events being dispatched is to throw a BPMN event. Please bear in mind that it only makes sense to throw BPMN-events with certain kinds of Flowable event types. For example, throwing a BPMN event when the process-instance is deleted will result in an error. The snippet below shows how to throw a signal inside process-instance, throw a signal to an external process (global), throw a message-event inside the process-instance and throw an error-event inside the process-instance. Instead of using the class or delegateExpression, the attribute throwEvent is used, along with an additional attribute, specific to the type of event being thrown.

    <process id="testEventListeners">
      <extensionElements>
        <flowable:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
      </extensionElements>
    </process>

    <process id="testEventListeners">
      <extensionElements>
        <flowable:eventListener throwEvent="globalSignal" signalName="My signal" events="TASK_ASSIGNED" />
      </extensionElements>
    </process>

    <process id="testEventListeners">
      <extensionElements>
        <flowable:eventListener throwEvent="message" messageName="My message" events="TASK_ASSIGNED" />
      </extensionElements>
    </process>

    <process id="testEventListeners">
      <extensionElements>
        <flowable:eventListener throwEvent="error" errorCode="123" events="TASK_ASSIGNED" />
      </extensionElements>
    </process>

If additional logic is needed to decide whether or not to throw the BPMN-event, it’s possible to extend the listener-classes provided by Flowable. By overriding the isValidEvent(FlowableEvent event) in your subclass, the BPMN-event throwing can be prevented. The classes involved are +org.flowable.engine.test.api.event.SignalThrowingEventListenerTest, org.flowable.engine.impl.bpmn.helper.MessageThrowingEventListener and org.flowable.engine.impl.bpmn.helper.ErrorThrowingEventListener.

#### Notes on listeners on a process-definition

-   Event-listeners can only be declared on the process element, as a child-element of the extensionElements. Listeners cannot be defined on individual activities in the process.

-   Expressions used in the delegateExpression do not have access to the execution-context, as other expressions (for example, in gateways) have. They can only reference beans defined in the beans property of the process engine configuration or when using Spring (and the beans property is absent) to any spring-bean that implements the listener interface.

-   When using the class attribute of a listener, there will only be a single instance of that class created. Make sure the listener implementations do not rely on member-fields or ensure safe usage from multiple threads/contexts.

-   When an illegal event-type is used in the events attribute or illegal throwEvent value is used, an exception will be thrown when the process-definition is deployed (effectively failing the deployment). When an illegal value for class or delegateExecution is supplied (either a nonexistent class, a nonexistent bean reference or a delegate not implementing listener interface), an exception will be thrown when the process is started (or when the first valid event for that process-definition is dispatched to the listener). Make sure the referenced classes are on the classpath and that the expressions resolve to a valid instance.

### Dispatching events through API

We opened up the event-dispatching mechanism through the API, to allow you to dispatch custom events to any listeners that are registered in the engine. It’s recommended (although not enforced) to only dispatch FlowableEvents with type CUSTOM. Dispatching the event can be done using the RuntimeService:

    /**
     * Dispatches the given event to any listeners that are registered.
     * @param event event to dispatch.
     *
     * @throws FlowableException if an exception occurs when dispatching the event or
     * when the {@link FlowableEventDispatcher} is disabled.
     * @throws FlowableIllegalArgumentException when the given event is not suitable for dispatching.
     */
     void dispatchEvent(FlowableEvent event);

### Supported event types

Listed below are all event types that can occur in the engine. Each type corresponds to an enum value in the org.flowable.common.engine.api.delegate.event.FlowableEventType (or org.flowable.idm.api.event.FlowableIdmEventType for identity management events).

<table>
<caption>Supported events</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Event name</th>
<th>Description</th>
<th>Event classes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>ENGINE_CREATED</p></td>
<td><p>The process-engine this listener is attached to has been created and is ready for API-calls.</p></td>
<td><p>org.flowable...FlowableEvent</p></td>
</tr>
<tr class="even">
<td><p>ENGINE_CLOSED</p></td>
<td><p>The process-engine this listener is attached to has been closed. API-calls to the engine are no longer possible.</p></td>
<td><p>org.flowable...FlowableEvent</p></td>
</tr>
<tr class="odd">
<td><p>ENTITY_CREATED</p></td>
<td><p>A new entity is created. The new entity is contained in the event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>ENTITY_INITIALIZED</p></td>
<td><p>A new entity has been created and is fully initialized. If any children are created as part of the creation of an entity, this event will be fired AFTER the create/initialisation of the child entities as opposed to the ENTITY_CREATE event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>ENTITY_UPDATED</p></td>
<td><p>An existing entity is updated. The updated entity is contained in the event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>ENTITY_DELETED</p></td>
<td><p>An existing entity is deleted. The deleted entity is contained in the event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>ENTITY_SUSPENDED</p></td>
<td><p>An existing entity is suspended. The suspended entity is contained in the event. Will be dispatched for ProcessDefinitions, ProcessInstances and Tasks.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>ENTITY_ACTIVATED</p></td>
<td><p>An existing entity is activated. The activated entity is contained in the event. Will be dispatched for ProcessDefinitions, ProcessInstances and Tasks.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>JOB_EXECUTION_SUCCESS</p></td>
<td><p>A job has been executed successfully. The event contains the job that was executed.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>JOB_EXECUTION_FAILURE</p></td>
<td><p>The execution of a job has failed. The event contains the job that was executed and the exception.</p></td>
<td><p>org.flowable...FlowableEntityEvent and org.flowable...FlowableExceptionEvent</p></td>
</tr>
<tr class="odd">
<td><p>JOB_RETRIES_DECREMENTED</p></td>
<td><p>The number of job retries have been decremented due to a failed job. The event contains the job that was updated.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>TIMER_SCHEDULED</p></td>
<td><p>A timer job has been created and is scheduled for being executed at a future point in time.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>TIMER_FIRED</p></td>
<td><p>A timer has been fired. The event contains the job that was executed.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>JOB_CANCELED</p></td>
<td><p>A job has been canceled. The event contains the job that was canceled. Job can be canceled by API call, task was completed and associated boundary timer was canceled, on the new process definition deployment.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>ACTIVITY_STARTED</p></td>
<td><p>An activity is starting to execute</p></td>
<td><p>org.flowable...FlowableActivityEvent</p></td>
</tr>
<tr class="even">
<td><p>ACTIVITY_COMPLETED</p></td>
<td><p>An activity is completed successfully</p></td>
<td><p>org.flowable...FlowableActivityEvent</p></td>
</tr>
<tr class="odd">
<td><p>ACTIVITY_CANCELLED</p></td>
<td><p>An activity is going to be canceled. There can be three reasons for activity cancellation (MessageEventSubscriptionEntity, SignalEventSubscriptionEntity, TimerEntity).</p></td>
<td><p>org.flowable...FlowableActivityCancelledEvent</p></td>
</tr>
<tr class="even">
<td><p>ACTIVITY_SIGNALED</p></td>
<td><p>An activity received a signal</p></td>
<td><p>org.flowable...FlowableSignalEvent</p></td>
</tr>
<tr class="odd">
<td><p>ACTIVITY_MESSAGE_RECEIVED</p></td>
<td><p>An activity received a message. Dispatched before the activity receives the message. When received, a ACTIVITY_SIGNAL or ACTIVITY_STARTED will be dispatched for this activity, depending on the type (boundary-event or event-subprocess start-event)</p></td>
<td><p>org.flowable...FlowableMessageEvent</p></td>
</tr>
<tr class="even">
<td><p>ACTIVITY_MESSAGE_WAITING</p></td>
<td><p>An activity has created a message event subscription and is waiting to receive.</p></td>
<td><p>org.flowable...FlowableMessageEvent</p></td>
</tr>
<tr class="odd">
<td><p>ACTIVITY_MESSAGE_CANCELLED</p></td>
<td><p>An activity for which a message event subscription has been created is canceled and thus receiving the message will not trigger this particular message anymore.</p></td>
<td><p>org.flowable...FlowableMessageEvent</p></td>
</tr>
<tr class="even">
<td><p>ACTIVITY_ERROR_RECEIVED</p></td>
<td><p>An activity has received an error event. Dispatched before the actual error has been handled by the activity. The event’s activityId contains a reference to the error-handling activity. This event will be either followed by a ACTIVITY_SIGNALLED event or ACTIVITY_COMPLETE for the involved activity, if the error was delivered successfully.</p></td>
<td><p>org.flowable...FlowableErrorEvent</p></td>
</tr>
<tr class="odd">
<td><p>UNCAUGHT_BPMN_ERROR</p></td>
<td><p>An uncaught BPMN error has been thrown. The process did not have any handlers for that specific error. The event’s activityId will be empty.</p></td>
<td><p>org.flowable...FlowableErrorEvent</p></td>
</tr>
<tr class="even">
<td><p>ACTIVITY_COMPENSATE</p></td>
<td><p>An activity is about to be compensated. The event contains the id of the activity that is will be executed for compensation.</p></td>
<td><p>org.flowable...FlowableActivityEvent</p></td>
</tr>
<tr class="odd">
<td><p>MULTI_INSTANCE_ACTIVITY_STARTED</p></td>
<td><p>A multi-instance activity is starting to execute</p></td>
<td><p>org.flowable...FlowableMultiInstanceActivityEvent</p></td>
</tr>
<tr class="even">
<td><p>MULTI_INSTANCE_ACTIVITY_COMPLETED</p></td>
<td><p>A multi-instance activity completed successfully</p></td>
<td><p>org.flowable...FlowableMultiInstanceActivityEvent</p></td>
</tr>
<tr class="odd">
<td><p>MULTI_INSTANCE_ACTIVITY_CANCELLED</p></td>
<td><p>A multi-instance activity is going to be canceled. There can be three reasons for activity cancellation (MessageEventSubscriptionEntity, SignalEventSubscriptionEntity, TimerEntity).</p></td>
<td><p>org.flowable...FlowableMultiInstanceActivityCancelledEvent</p></td>
</tr>
<tr class="even">
<td><p>VARIABLE_CREATED</p></td>
<td><p>A variable has been created. The event contains the variable name, value and related execution and task (if any).</p></td>
<td><p>org.flowable...FlowableVariableEvent</p></td>
</tr>
<tr class="odd">
<td><p>VARIABLE_UPDATED</p></td>
<td><p>An existing variable has been updated. The event contains the variable name, updated value and related execution and task (if any).</p></td>
<td><p>org.flowable...FlowableVariableEvent</p></td>
</tr>
<tr class="even">
<td><p>VARIABLE_DELETED</p></td>
<td><p>An existing variable has been deleted. The event contains the variable name, last known value and related execution and task (if any).</p></td>
<td><p>org.flowable...FlowableVariableEvent</p></td>
</tr>
<tr class="odd">
<td><p>TASK_ASSIGNED</p></td>
<td><p>A task has been assigned to a user. The event contains the task</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>TASK_CREATED</p></td>
<td><p>A task has been created. This is dispatched after the ENTITY_CREATE event. If the task is part of a process, this event will be fired before the task listeners are executed.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>TASK_COMPLETED</p></td>
<td><p>A task has been completed. This is dispatched before the ENTITY_DELETE event. If the task is part of a process, this event will be fired before the process has moved on and will be followed by a ACTIVITY_COMPLETE event, targeting the activity that represents the completed task.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>TASK_OWNER_CHANGED</p></td>
<td><p>A task owner has been changed. This is dispatched before the ENTITY_UPDATE event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>TASK_PRIORITY_CHANGED</p></td>
<td><p>A task priority has been changed. This is dispatched before the ENTITY_UPDATE event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>TASK_DUEDATE_CHANGED</p></td>
<td><p>A task due date has been changed. This is dispatched before the ENTITY_UPDATE event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>TASK_NAME_CHANGED</p></td>
<td><p>A task name has been changed. This is dispatched before the ENTITY_UPDATE event.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>PROCESS_CREATED</p></td>
<td><p>A process instance has been created. All basic properties have been set, but variables not yet.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>PROCESS_STARTED</p></td>
<td><p>A process instance has been started. Dispatched when starting a process instance previously created. The event PROCESS_STARTED is dispatched after the associated event ENTITY_INITIALIZED and after the variables have been set.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="even">
<td><p>PROCESS_COMPLETED</p></td>
<td><p>A process has been completed, meaning all executions have stopped for the process instance. Dispatched after the last activity ACTIVITY_COMPLETED event. Process is completed when it reaches state in which process instance does not have any transition to take.</p></td>
<td><p>org.flowable...FlowableEntityEvent</p></td>
</tr>
<tr class="odd">
<td><p>PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT</p></td>
<td><p>A process has been completed by arriving at a terminate end event.</p></td>
<td><p>org.flowable...FlowableProcessTerminatedEvent</p></td>
</tr>
<tr class="even">
<td><p>PROCESS_CANCELLED</p></td>
<td><p>A process has been canceled. Dispatched before the process instance is deleted from runtime. A process instance can for example be canceled by the API call RuntimeService.deleteProcessInstance, by an interrupting boundary event on a call activity, …​</p></td>
<td><p>org.flowable...FlowableCancelledEvent</p></td>
</tr>
<tr class="odd">
<td><p>MEMBERSHIP_CREATED</p></td>
<td><p>A user has been added to a group. The event contains the ids of the user and group involved. This event type is defined in org.flowable.idm.api.event.FlowableIdmEventType.</p></td>
<td><p>org.flowable...FlowableMembershipEvent</p></td>
</tr>
<tr class="even">
<td><p>MEMBERSHIP_DELETED</p></td>
<td><p>A user has been removed from a group. The event contains the ids of the user and group involved. This event type is defined in org.flowable.idm.api.event.FlowableIdmEventType.</p></td>
<td><p>org.flowable...FlowableMembershipEvent</p></td>
</tr>
<tr class="odd">
<td><p>MEMBERSHIPS_DELETED</p></td>
<td><p>All members will be removed from a group. The event is thrown before the members are removed, so they are still accessible. No individual MEMBERSHIP_DELETED events will be thrown if all members are deleted at once, for performance reasons. This event type is defined in org.flowable.idm.api.event.FlowableIdmEventType.</p></td>
<td><p>org.flowable...FlowableMembershipEvent</p></td>
</tr>
</tbody>
</table>

All ENTITY\_\\\* events are related to entities inside the engine. The list below show an overview of what entity-events are dispatched for which entities:

-   **ENTITY\_CREATED, ENTITY\_INITIALIZED, ENTITY\_DELETED**: Attachment, Comment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.

-   **ENTITY\_UPDATED**: Attachment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.

-   **ENTITY\_SUSPENDED, ENTITY\_ACTIVATED**: ProcessDefinition, ProcessInstance/Execution, Task.

### Additional remarks

**Listeners are only notified for events dispatched from the engine they are registered with.** So if you have different engines - running against the same database - only events that originated in the engine the listener is registered to are dispatched to that listener. The events that occur in other engines are not dispatched to the listeners, regardless of whether they are running in the same JVM or not.

Certain event-types (related to entities) expose the targeted entity. Depending on the type or event, these entities cannot be updated anymore (for example, when the entity is deleted). If possible, use the EngineServices exposed by the event to interact in a safe way with the engine. Even then, you need to be cautious with updates/operations on entities that are involved in the dispatched event.

No entity-events are dispatched related to history, as they all have a runtime-counterpart that dispatch their events.

---

### Docusaurus Docs Bpmn Ch04 API (`docs/docusaurus/docs/bpmn/ch04-API.md`)

---
id: ch04-API
title: The Flowable API
---

## The Process Engine API and services

The engine API is the most common way of interacting with Flowable. The main starting point is the ProcessEngine, which can be created in several ways as described in the [configuration section](bpmn/ch03-Configuration.md#creating-a-processengine). From the ProcessEngine, you can obtain the various services that contain the workflow/BPM methods. ProcessEngine and the services objects are thread safe, so you can keep a reference to one of those for a whole server.



    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    RuntimeService runtimeService = processEngine.getRuntimeService();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    TaskService taskService = processEngine.getTaskService();
    ManagementService managementService = processEngine.getManagementService();
    IdentityService identityService = processEngine.getIdentityService();
    HistoryService historyService = processEngine.getHistoryService();
    FormService formService = processEngine.getFormService();
    DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();

ProcessEngines.getDefaultProcessEngine() will initialize and build a process engine the first time it is called and afterwards always return the same process engine. Proper creation and closing of all process engines can be done with ProcessEngines.init() and ProcessEngines.destroy().

The ProcessEngines class will scan for all flowable.cfg.xml and flowable-context.xml files. For all flowable.cfg.xml files, the process engine will be built in the typical Flowable way: ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine(). For all flowable-context.xml files, the process engine will be built in the Spring way: first the Spring application context is created and then the process engine is obtained from that application context.

All services are stateless. This means that you can easily run Flowable on multiple nodes in a cluster, each going to the same database, without having to worry about which machine actually executed previous calls. Any call to any service is idempotent regardless of where it is executed.

The **RepositoryService** is probably the first service needed when working with the Flowable engine. This service offers operations for managing and manipulating deployments and process definitions. Without going into much detail here, a process definition is a Java counterpart of the BPMN 2.0 process. It is a representation of the structure and behavior of each of the steps of a process. A deployment is the unit of packaging within the Flowable engine. A deployment can contain multiple BPMN 2.0 XML files and any other resource. The choice of what is included in one deployment is up to the developer. It can range from a single process BPMN 2.0 XML file to a whole package of processes and relevant resources (for example, the deployment 'hr-processes' could contain everything related to HR processes). The RepositoryService can deploy such packages. Deploying a deployment means it is uploaded to the engine, where all processes are inspected and parsed before being stored in the database. From that point on, the deployment is known to the system and any process included in the deployment can now be started.

Furthermore, this service allows you to:

-   Query on deployments and process definitions known to the engine.

-   Suspend and activate deployments as a whole or specific process definitions. Suspending means no further operations can be performed on them, while activation is the opposite and enables operations again.

-   Retrieve various resources, such as files contained within the deployment or process diagrams that were auto-generated by the engine.

-   Retrieve a POJO version of the process definition, which can be used to introspect the process using Java rather than XML.

While the RepositoryService is mostly about static information (data that doesn’t change, or at least not a lot), the **RuntimeService** is quite the opposite. It deals with starting new process instances of process definitions. As said above, a process definition defines the structure and behavior of the different steps in a process. A process instance is one execution of such a process definition. For each process definition there typically are many instances running at the same time. The RuntimeService also is the service that is used to retrieve and store process variables. This is data that is specific to the given process instance and can be used by various constructs in the process (for example, an exclusive gateway often uses process variables to determine which path is chosen to continue the process). The Runtimeservice also allows you to query on process instances and executions. Executions are a representation of the 'token' concept of BPMN 2.0. Basically, an execution is a pointer to where the process instance currently is. Lastly, the RuntimeService is used whenever a process instance is waiting for an external trigger and the process needs to be continued. A process instance can have various wait states and this service contains various operations to 'signal' to the instance that the external trigger is received and the process instance can be continued.

Tasks that need to be performed by human users of the system are core to a BPM engine such as Flowable. Everything around tasks is grouped in the **TaskService**, such as:

-   Querying tasks assigned to users or groups

-   Creating new *standalone* tasks. These are tasks that are not related to a process instance.

-   Manipulating to which user a task is assigned or which users are in some way involved with the task.

-   Claiming and completing a task. Claiming means that someone decided to be the assignee for the task, meaning that this user will complete the task. Completing means 'doing the work of the tasks'. Typically this is filling in a form of sorts.

The **IdentityService** is pretty simple. It supports the management (creation, update, deletion, querying, …​) of groups and users. It is important to understand that Flowable actually doesn’t do any checking on users at runtime. For example, a task could be assigned to any user, but the engine doesn’t verify whether that user is known to the system. This is because the Flowable engine can also be used in conjunction with services such as LDAP, Active Directory, and so on.

The **FormService** is an optional service. Meaning that Flowable can be used quite happily without it, without sacrificing any functionality. This service introduces the concept of a *start form* and a *task form*. A *start form* is a form that is shown to the user before the process instance is started, while a *task form* is the form that is displayed when a user wants to complete a form. Flowable allows the specification of these forms in the BPMN 2.0 process definition. This service exposes this data in an easy way to work with. But again, this is optional, as forms don’t need to be embedded in the process definition.

The **HistoryService** exposes all historical data gathered by the Flowable engine. When executing processes, a lot of data can be kept by the engine (this is configurable), such as process instance start times, who did which tasks, how long it took to complete the tasks, which path was followed in each process instance, and so on. This service exposes mainly query capabilities to access this data.

The **ManagementService** is typically not needed when coding custom application using Flowable. It allows the retrieval of information about the database tables and table metadata. Furthermore, it exposes query capabilities and management operations for jobs. Jobs are used in Flowable for various things, such as timers, asynchronous continuations, delayed suspension/activation, and so on. Later on, these topics will be discussed in more detail.

The **DynamicBpmnService** can be used to change part of the process definition without needing to redeploy it. You can, for example, change the assignee definition for a user task in a process definition, or change the class name of a service task.

For more detailed information on the service operations and the engine API, see [the javadocs](http://www.flowable.org/docs/javadocs/index.html).

## Exception strategy

The base exception in Flowable is the org.flowable.engine.FlowableException, an unchecked exception. This exception can be thrown at all times by the API, but 'expected' exceptions that happen in specific methods are documented in [the javadocs](http://www.flowable.org/docs/javadocs/index.html). For example, an extract from TaskService:

    /**
     * Called when the task is successfully executed.
     * @param taskId the id of the task to complete, cannot be null.
     * @throws FlowableObjectNotFoundException when no task exists with the given id.
     */
     void complete(String taskId);

In the example above, when an id is passed for which no task exists, an exception will be thrown. Also, since the javadoc **explicitly states that taskId cannot be null, an FlowableIllegalArgumentException will be thrown when null is passed**.

Even though we want to avoid a big exception hierarchy, the following subclasses are thrown in specific cases. All other errors that occur during process-execution or API-invocation that don’t fit into the possible exceptions below, are thrown as regular FlowableExceptions.

-   FlowableWrongDbException: Thrown when the Flowable engine discovers a mismatch between the database schema version and the engine version.

-   FlowableOptimisticLockingException: Thrown when an optimistic locking occurs in the data store caused by concurrent access of the same data entry.

-   FlowableClassLoadingException: Thrown when a class requested to load was not found or when an error occurred while loading it (e.g. JavaDelegates, TaskListeners, …​).

-   FlowableObjectNotFoundException: Thrown when an object that is requested or actioned does not exist.

-   FlowableIllegalArgumentException: An exception indicating that an illegal argument has been supplied in a Flowable API-call, an illegal value was configured in the engine’s configuration or an illegal value has been supplied or an illegal value is used in a process-definition.

-   FlowableTaskAlreadyClaimedException: Thrown when a task is already claimed, when the taskService.claim(...) is called.

## Query API

There are two ways of querying data from the engine: the query API and native queries. The Query API allows you to program completely typesafe queries with a fluent API. You can add various conditions to your queries (all of which are applied together as a logical AND) and precisely one ordering. The following code shows an example:

    List<Task> tasks = taskService.createTaskQuery()
        .taskAssignee("kermit")
        .processVariableValueEquals("orderId", "0815")
        .orderByDueDate().asc()
        .list();

Sometimes you need more powerful queries, for example, queries using an OR operator or restrictions you cannot express using the Query API. For these cases, we have native queries, which allow you to write your own SQL queries. The return type is defined by the Query object you use and the data is mapped into the correct objects (Task, ProcessInstance, Execution, …​). Since the query will be fired at the database you have to use table and column names as they are defined in the database; this requires some knowledge about the internal data structure and it is recommended to use native queries with care. The table names can be retrieved through the API to keep the dependency as small as possible.

    List<Task> tasks = taskService.createNativeTaskQuery()
      .sql("SELECT * FROM " + managementService.getTableName(Task.class) +
          " T WHERE T.NAME_ = #{taskName}")
      .parameter("taskName", "gonzoTask")
      .list();

    long count = taskService.createNativeTaskQuery()
      .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, " +
          managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_")
      .count();

## Variables

Every process instance needs and uses data to execute the steps it’s made up of. In Flowable, this data is called *variables*, which are stored in the database. Variables can be used in expressions (for example, to select the correct outgoing sequence flow in an exclusive gateway), in Java service tasks when calling external services (for example to provide the input or store the result of the service call), and so on.

A process instance can have variables (called *process variables*), but also *executions* (which are specific pointers to where the process is active) and user tasks can have variables. A process instance can have any number of variables. Each variable is stored in a row in the *ACT\_RU\_VARIABLE* database table.

All of the *startProcessInstanceXXX* methods have an optional parameters to provide the variables when the process instance is created and started. For example, from the *RuntimeService*:

    ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);

Variables can be added during process execution. For example, (*RuntimeService*):

    void setVariable(String executionId, String variableName, Object value);
    void setVariableLocal(String executionId, String variableName, Object value);
    void setVariables(String executionId, Map<String, ? extends Object> variables);
    void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);

Note that variables can be set *local* for a given execution (remember, a process instance consists of a tree of executions). The variable will only be visible on that execution and not higher in the tree of executions. This can be useful if data shouldn’t be propagated to the process instance level, or the variable has a new value for a certain path in the process instance (for example, when using parallel paths).

Variables can also be retrieved, as shown below. Note that similar methods exist on the *TaskService*. This means that tasks, like executions, can have local variables that are 'alive' just for the duration of the task.

    Map<String, Object> getVariables(String executionId);
    Map<String, Object> getVariablesLocal(String executionId);
    Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
    Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
    Object getVariable(String executionId, String variableName);
    <T> T getVariable(String executionId, String variableName, Class<T> variableClass);

Variables are often used in [Java delegates](bpmn/ch07b-BPMN-Constructs.md#java-service-task), [expressions](bpmn/ch04-API.md#expressions), execution- or tasklisteners, scripts, and so on. In those constructs, the current *execution* or *task* object is available and it can be used for variable setting and/or retrieval. The simplest methods are these:

    execution.getVariables();
    execution.getVariables(Collection<String> variableNames);
    execution.getVariable(String variableName);

    execution.setVariables(Map<String, object> variables);
    execution.setVariable(String variableName, Object value);

Note that a variant with *local* is also available for all of the above.

For historical (and backwards-compatibility reasons), when doing any of the calls above, behind the scenes **all** variables will be fetched from the database. This means that if you have 10 variables, but only get one through *getVariable("myVariable")*, behind the scenes the other 9 will be fetched and cached. This is not necessarily bad, as subsequent calls will not hit the database again. For example, when your process definition has three sequential service tasks (and thus one database transaction), using one call to fetch all variables in the first service task might be better then fetching the variables needed in each service task separately. Note that this applies **both** for getting and setting variables.

Of course, when using a lot of variables or simply when you want tight control on the database query and traffic, this is not appropriate. Additional methods have been introduced to give a tighter control on this, by adding in new methods that have an optional parameter that tells the engine whether or not to fetch and cache all variables:

    Map<String, Object> getVariables(Collection<String> variableNames, boolean fetchAllVariables);
    Object getVariable(String variableName, boolean fetchAllVariables);
    void setVariable(String variableName, Object value, boolean fetchAllVariables);

When using *true* for the parameter *fetchAllVariables*, the behavior will be exactly as described above: when getting or setting a variable, all other variables will be fetched and cached.

However, when using *false* as value, a specific query will be used and no other variables will be fetched or cached. Only the value of the variable in question here will be cached for subsequent use.

## Transient variables

Transient variables are variables that behave like regular variables, but are not persisted. Typically, transient variables are used for advanced use cases. When in doubt, use a regular process variable.

The following applies for transient variables:

-   There is no history stored at all for transient variables.

-   Like *regular* variables, transient variables are put on the *highest parent* when set. This means that when setting a variable on an execution, the transient variable is actually stored on the process instance execution. Like regular variables, a *local* variant of the method exists if the variable is set on the specific execution or task.

-   A transient variable can only be accessed before the next 'wait state' in the process definition. After that, they are gone. Here, the wait state means the point in the process instance where it is persisted to the data store. Note that an *async* activity is also a 'wait state' in this definition!

-   Transient variables can only be set by the *setTransientVariable(name, value)*, but transient variables are also returned when calling *getVariable(name)* (a *getTransientVariable(name)* also exists, that only checks the transient variables). The reason for this is to make the writing of expressions easy and existing logic using variables works for both types.

-   A transient variable *shadows* a persistent variable with the same name. This means that when both a persistent and transient variable is set on a process instance and *getVariable("someVariable")* is called, the transient variable value will be returned.

You can set and get transient variables in most places where regular variables are exposed:

-   On *DelegateExecution* in *JavaDelegate* implementations

-   On *DelegateExecution* in *ExecutionListener* implementations and on *DelegateTask* on *TaskListener* implementations

-   In script task via the *execution* object

-   When starting a process instance through the runtime service

-   When completing a task

-   When calling the *runtimeService.trigger* method

The methods follow the naming convention of the regular process variables:

    void setTransientVariable(String variableName, Object variableValue);
    void setTransientVariableLocal(String variableName, Object variableValue);
    void setTransientVariables(Map<String, Object> transientVariables);
    void setTransientVariablesLocal(Map<String, Object> transientVariables);

    Object getTransientVariable(String variableName);
    Object getTransientVariableLocal(String variableName);

    Map<String, Object> getTransientVariables();
    Map<String, Object> getTransientVariablesLocal();

    void removeTransientVariable(String variableName);
    void removeTransientVariableLocal(String variableName);

The following BPMN diagram shows a typical example:



Let’s assume the 'Fetch Data' service task calls some remote service (for example, using REST). Let’s also assume some configuration parameters are needed and need to be provided when starting the process instance. Also, these configuration parameters are not important for historical audit purposes, so we pass them as transient variables:

    ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
           .processDefinitionKey("someKey")
           .transientVariable("configParam01", "A")
           .transientVariable("configParam02", "B")
           .transientVariable("configParam03", "C")
           .start();

Note that the transient variables will be available until the user task is reached and persisted to the database. For example, in the 'Additional Work' user task they are no longer available. Also note that if 'Fetch Data' had been asynchronous, they wouldn’t be available after that step either.

The 'Fetch Data' (simplified) could be something like:

    public static class FetchDataServiceTask implements JavaDelegate {
      public void execute(DelegateExecution execution) {
        String configParam01 = (String) execution.getVariable(configParam01);
        // ...

        RestResponse restResponse = executeRestCall();
        execution.setTransientVariable("response", restResponse.getBody());
        execution.setTransientVariable("status", restResponse.getStatus());
      }
    }

The 'Process Data' would get the response transient variable, parse it and store the relevant data in real process variables as we need them later.

The condition on the sequence flow leaving the exclusive gateway are oblivious to whether persistent or transient variables are used (in this case, the *status* transient variable):

    <conditionExpression xsi:type="tFormalExpression">${status == 200}</conditionExpression>

## Expressions

Flowable uses UEL for expression-resolving. UEL stands for *Unified Expression Language* and is part of the EE6 specification (see [the EE6 specification](http://docs.oracle.com/javaee/6/tutorial/doc/gjddd.html) for detailed information).

Expressions can be used in, for example, [Java Service tasks](bpmn/ch07b-BPMN-Constructs.md#xml-representation), [Execution Listeners](bpmn/ch07b-BPMN-Constructs.md#execution-listener), [Task Listeners](bpmn/ch07b-BPMN-Constructs.md#task-listener) and [Conditional sequence flows](bpmn/ch07b-BPMN-Constructs.md#xml-representation). Although there are two types of expressions, value-expression and method-expression, Flowable abstracts this so they can both be used where an expression is expected.

-   **Value expression**: resolves to a value. By default, all process variables are available to use. Also, all spring-beans (if using Spring) are available to use in expressions. Some examples:



    ${myVar}
    ${myBean.myProperty}

-   **Method expression**: invokes a method with or without parameters. **When invoking a method without parameters, be sure to add empty parentheses after the method-name (as this distinguishes the expression from a value expression).** The passed parameters can be literal values or expressions that are resolved themselves. Examples:



    ${printer.print()}
    ${myBean.addNewOrder('orderName')}
    ${myBean.doSomething(myVar, execution)}

Note that these expressions support resolving primitives (including comparing them), beans, lists, arrays and maps.

On top of all process variables, there are a few default objects available that can be used in expressions:

-   execution: The DelegateExecution holds additional information about the ongoing execution.

-   task: The DelegateTask holds additional information about the current Task. **Note: Only works in expressions evaluated from task listeners.**

-   authenticatedUserId: The id of the user that is currently authenticated. If no user is authenticated, the variable is not available.

-   variableContainer: The VariableContainer for which the expression is being resolved for.

For more concrete usage and examples, check out [Expressions in Spring](bpmn/ch05-Spring.md#expressions), [Java Service tasks](bpmn/ch07b-BPMN-Constructs.md#xml-representation), [Execution Listeners](bpmn/ch07b-BPMN-Constructs.md#execution-listener), [Task Listeners](bpmn/ch07b-BPMN-Constructs.md#task-listener) or [Conditional sequence flows](bpmn/ch07b-BPMN-Constructs.md#xml-representation).

## Expression functions

\[Experimental\] Expression functions have been added in version 6.4.0.

To make working with process variables easier, a set of out-of-the-box functions is available, under the *variables* namespace.

-   **variables:get(varName)**: Retrieves the value of a variable. The main difference with writing the variable name directly in the expression is that using this function won’t throw an exception when the variable doesn’t exist. For example *${myVariable == "hello"}* would throw an exception if *myVariable* doesn’t exist, but *${var:get(myVariable) == 'hello'}* will just work.

-   **variables:getOrDefault(varName, defaultValue)**: similar to *get*, but with the option of providing a default value which is returned when the variable isn’t set or the value is *null*.

-   **variables:exists(varName)**: Returns *true* if the variable has a non-null value.

-   **variables:isEmpty(varName)** (alias *:empty*) : Checks if the variable value is not empty. Depending on the variable type, the behavior is the following:

    -   For String variables, the variable is deemed empty if it’s the empty string.

    -   For java.util.Collection variables, *true* is returned if the collection has no elements.

    -   For ArrayNode variables, *true* is returned if there are no elements

    -   In case the variable is *null*, *true* is always returned

-   **variables:isNotEmpty(varName)** (alias *:notEmpty*) : the reverse operation of *isEmpty*.

-   **variables:equals(varName, value)** (alias *:eq*) : checks if a variable is equal to a given value. This is a shorthand function for an expression that would otherwise be written as *${execution.getVariable("varName") != null && execution.getVariable("varName") == value}*.

    -   If the variable value is null, false is returned (unless compared to null).

-   **variables:notEquals(varName, value)** (alias *:ne*) : the reverse comparison of *equals*.

-   **variables:contains(varName, value1, value2, …​)**: checks if **all** values provided are contained within a variable. Depending on the variable type, the behavior is the following:

    -   For String variables, the passed values are used as substrings that need to be part of the variable

    -   For java.util.Collection variables, all the passed values need to be an element of the collection (regular *contains* semantics).

    -   For ArrayNode variables: supports checking if the arraynode contains a JsonNode for the types that are supported as variable type

    -   When the variable value is null, false is returned in all cases. When the variable value is not null, and the instance type is not one of the types above, false will be returned.

-   **variables:containsAny(varName, value1, value2, …​)** : similar to the *contains* function, but *true* will be returned if **any** (and not all) the passed values is contained in the variable.

-   **variables:base64(varName)** : converts a Binary or String variable to a Base64 String

-   Comparator functions:

    -   **variables:lowerThan(varName, value)** (alias *:lessThan* or *:lt*) : shorthand for *${execution.getVariable("varName") != null && execution.getVariable("varName") &lt; value}*

    -   **variables:lowerThanOrEquals(varName, value)** (alias *:lessThanOrEquals* or *:lte*) : similar, but now for *&lt; =*

    -   **variables:greaterThan(varName, value)** (alias *:gt*) : similar, but now for *&gt;*

    -   **variables:greaterThanOrEquals(varName, value)** (alias *:gte*) : similar, but now for *&gt; =*

The *variables* namespace is aliased to *vars* or *var*. So *variables:get(varName)* is equivalent to writing *vars:get(varName)* or *var:get(varName)*. Note that it’s not needed to put quotes around the variable name: *var:get(varName)* is equivalent to *var:get(\\'varName')* or *var:get("varName")*.

Also note that in none of the functions above the *execution* needs to be passed into the function (as would be needed when not using a function). The engine will inject the appropriate variable scope when invoking the function. This also means that these functions can be used in exactly the same way when writing expression in CMMN case definitions.

Additionally, it’s possible to register custom functions that can be used in expressions. See the org.flowable.common.engine.api.delegate.FlowableFunctionDelegate interface for more information.

## Unit testing

Business processes are an integral part of software projects and they should be tested in the same way normal application logic is tested: with unit tests. Since Flowable is an embeddable Java engine, writing unit tests for business processes is as simple as writing regular unit tests.

Flowable supports JUnit Jupiter styles of unit testing.

In the JUnit Jupiter style one needs to use the org.flowable.engine.test.FlowableTest annotation or register the org.flowable.engine.test.FlowableExtension manually.
The FlowableTest annotation is just a meta-annotation and does the registration of the FlowableExtension (i.e., it does @ExtendWith(FlowableExtension.class)).
This will make the ProcessEngine and the services available as parameters into the test and lifecycle methods (@BeforeAll, @BeforeEach, @AfterEach, @AfterAll).
Before each test the processEngine will be initialized by default with the flowable.cfg.xml resource on the classpath.
To specify a different configuration file, the org.flowable.engine.test.ConfigurationResource annotation needs to be used (see second example).
Process engines are cached statically over multiple unit tests when the configuration resource is the same.

By using FlowableExtension, you can annotate test methods with org.flowable.engine.test.Deployment.
When a test method is annotated with @Deployment, before each test the bpmn files defined in Deployment\#resources will be deployed.
In case there are no resources defined, a resource file of the form testClassName.testMethod.bpmn20.xml in the same package as the test class, will be deployed.
At the end of the test, the deployment will be deleted, including all related process instances, tasks, and so on.
See the Deployment class for more information.

Taking all that into account, a JUnit Jupiter test looks as follows:

**JUnit Jupiter test with default resource.**

    @FlowableTest
    class MyBusinessProcessTest {

      private ProcessEngine processEngine;
      private RuntimeService runtimeService;
      private TaskService taskService;

      @BeforeEach
      void setUp(ProcessEngine processEngine) {
        this.processEngine = processEngine;
        this.runtimeService = processEngine.getRuntimeService();
        this.taskService = processEngine.getTaskService();
      }

      @Test
      @Deployment
      void testSimpleProcess() {
        runtimeService.startProcessInstanceByKey("simpleProcess");

        Task task = taskService.createTaskQuery().singleResult();
        assertEquals("My Task", task.getName());

        taskService.complete(task.getId());
        assertEquals(0, runtimeService.createProcessInstanceQuery().count());
      }
    }

    With JUnit Jupiter you can also inject the id of the deployment (with +org.flowable.engine.test.DeploymentId+_) into your test and lifecycle methods.

**JUnit Jupiter test with a custom resource file.**

    @FlowableTest
    @ConfigurationResource("flowable.custom.cfg.xml")
    class MyBusinessProcessTest {

      private ProcessEngine processEngine;
      private RuntimeService runtimeService;
      private TaskService taskService;

      @BeforeEach
      void setUp(ProcessEngine processEngine) {
        this.processEngine = processEngine;
        this.runtimeService = processEngine.getRuntimeService();
        this.taskService = processEngine.getTaskService();
      }

      @Test
      @Deployment
      void testSimpleProcess() {
        runtimeService.startProcessInstanceByKey("simpleProcess");

        Task task = taskService.createTaskQuery().singleResult();
        assertEquals("My Task", task.getName());

        taskService.complete(task.getId());
        assertEquals(0, runtimeService.createProcessInstanceQuery().count());
      }
    }

## Debugging unit tests

When using the in-memory H2 database for unit tests, the following instructions allow you to easily inspect the data in the Flowable database during a debugging session. The screenshots here are taken in Eclipse, but the mechanism should be similar for other IDEs.

Suppose we have put a *breakpoint* somewhere in our unit test (in Eclipse this is done by double-clicking in the left border next to the code):



If we now run the unit test in *debug* mode (right-click in test class, select 'Run as' and then 'JUnit test'), the test execution halts at our breakpoint, where we can now inspect the variables of our test as shown in the right upper panel.



To inspect the Flowable data, open up the *'Display'* window (if this window isn’t there, open Window→Show View→Other and select *Display*.) and type (code completion is available) org.h2.tools.Server.createWebServer("-web").start()



Select the line you’ve just typed and right-click on it. Now select 'Display' (or execute the shortcut instead of right-clicking)



Now open up a browser and go to [<http://localhost:8082>](http://localhost:8082), and fill in the JDBC URL to the in-memory database (by default this is jdbc:h2:mem:flowable), and hit the connect button.



You can now see the Flowable data and use it to understand how and why your unit test is executing your process in a certain way.



## The process engine in a web application

The ProcessEngine is a thread-safe class and can easily be shared among multiple threads. In a web application, this means it is possible to create the process engine once when the container boots and shut down the engine when the container goes down.

The following code snippet shows how you can write a simple ServletContextListener to initialize and destroy process engines in a plain Servlet environment:

    public class ProcessEnginesServletContextListener implements ServletContextListener {

      public void contextInitialized(ServletContextEvent servletContextEvent) {
        ProcessEngines.init();
      }

      public void contextDestroyed(ServletContextEvent servletContextEvent) {
        ProcessEngines.destroy();
      }

    }

The contextInitialized method will delegate to ProcessEngines.init(). That will look for flowable.cfg.xml resource files on the classpath, and create a ProcessEngine for the given configurations (for example, multiple JARs with a configuration file). If you have multiple such resource files on the classpath, make sure they all have different names. When the process engine is needed, it can be fetched using:

    ProcessEngines.getDefaultProcessEngine()

or

    ProcessEngines.getProcessEngine("myName");

Of course, it is also possible to use any of the variants of creating a process engine,
as described in the [configuration section](bpmn/ch03-Configuration.md#creating-a-processengine).

The contextDestroyed method of the context-listener delegates to ProcessEngines.destroy(). That will properly close all initialized process engines.

---

### Docusaurus Docs Bpmn Ch05 Spring (`docs/docusaurus/docs/bpmn/ch05-Spring.md`)

---
id: ch05-Spring
title: Spring integration
---

While you can definitely use Flowable without Spring, we’ve provided some very nice integration features that are explained in this chapter.

## ProcessEngineFactoryBean

The ProcessEngine can be configured as a regular Spring bean. The starting point of the integration is the class org.flowable.spring.ProcessEngineFactoryBean. That bean takes a process engine configuration and creates the process engine. This means that the creation and configuration of properties for Spring is the same as documented in the [configuration section](bpmn/ch03-Configuration.md#creating-a-processengine). For Spring integration, the configuration and engine beans will look like this:

    <bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
        ...
    </bean>

    <bean id="processEngine" class="org.flowable.spring.ProcessEngineFactoryBean">
      <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

Note that the processEngineConfiguration bean now uses the org.flowable.spring.SpringProcessEngineConfiguration class.

## Transactions

We’ll explain the SpringTransactionIntegrationTest found in the Spring examples of the distribution step by step. Below is the Spring configuration file that we use in this example (you can find it in SpringTransactionIntegrationTest-context.xml). The section shown below contains the dataSource, transactionManager, processEngine and the Flowable engine services.

When passing the DataSource to the SpringProcessEngineConfiguration (using property "dataSource"), Flowable uses a org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy internally, which wraps the passed DataSource. This is done to make sure the SQL connections retrieved from the DataSource and the Spring transactions play well together. This implies that it’s no longer necessary to proxy the dataSource yourself in Spring configuration, although it’s still possible to pass a TransactionAwareDataSourceProxy into the SpringProcessEngineConfiguration. In this case, no additional wrapping will occur.

**Make sure when declaring a TransactionAwareDataSourceProxy in Spring configuration yourself that you don’t use it for resources that are already aware of Spring transactions (e.g. DataSourceTransactionManager and JPATransactionManager need the un-proxied dataSource).**

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                                 http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context
                                 http://www.springframework.org/schema/context/spring-context-2.5.xsd
                               http://www.springframework.org/schema/tx
                                 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

      <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="username" value="sa" />
        <property name="password" value="" />
      </bean>

      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
      </bean>

      <bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="databaseSchemaUpdate" value="true" />
        <property name="asyncExecutorActivate" value="false" />
      </bean>

      <bean id="processEngine" class="org.flowable.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
      </bean>

      <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
      <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
      <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
      <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
      <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />

    ...

The remainder of that Spring configuration file contains the beans and configuration that we’ll use in this particular example:

    <beans>
      ...
      <tx:annotation-driven transaction-manager="transactionManager"/>

      <bean id="userBean" class="org.flowable.spring.test.UserBean">
        <property name="runtimeService" ref="runtimeService" />
      </bean>

      <bean id="printer" class="org.flowable.spring.test.Printer" />

    </beans>

First, the application context is created using any of the ways supported by Spring. In this example, you could use a classpath XML resource to configure our Spring application context:

    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
        "org/flowable/examples/spring/SpringTransactionIntegrationTest-context.xml");

or, as it’s a test:

    @ContextConfiguration(
      "classpath:org/flowable/spring/test/transaction/SpringTransactionIntegrationTest-context.xml")

Then we can get the service beans and invoke methods on them. The ProcessEngineFactoryBean will have added an extra interceptor to the services that applies Propagation.REQUIRED transaction semantics on the Flowable service methods. So, for example, we can use the repositoryService to deploy a process like this:

    RepositoryService repositoryService =
      (RepositoryService) applicationContext.getBean("repositoryService");
    String deploymentId = repositoryService
      .createDeployment()
      .addClasspathResource("org/flowable/spring/test/hello.bpmn20.xml")
      .deploy()
      .getId();

The other way around also works. In this case, the Spring transaction will be around the userBean.hello() method and the Flowable service method invocation will join that same transaction.

    UserBean userBean = (UserBean) applicationContext.getBean("userBean");
    userBean.hello();

The UserBean looks like this. Remember, from above in the Spring bean configuration, we injected the repositoryService into the userBean.

    public class UserBean {

      /** injected by Spring */
      private RuntimeService runtimeService;

      @Transactional
      public void hello() {
        // here you can do transactional stuff in your domain model
        // and it will be combined in the same transaction as
        // the startProcessInstanceByKey to the Flowable RuntimeService
        runtimeService.startProcessInstanceByKey("helloProcess");
      }

      public void setRuntimeService(RuntimeService runtimeService) {
        this.runtimeService = runtimeService;
      }
    }

## Expressions

When using the ProcessEngineFactoryBean, all [expressions](bpmn/ch04-API.md#expressions) in the BPMN processes will also 'see' all the Spring beans, by default. It’s possible to limit the beans (even none) you want to expose in expressions using a map that you can configure. The example below exposes a single bean (printer), available to use under the key "printer". **To have NO beans exposed at all, just pass an empty list as 'beans' property on the SpringProcessEngineConfiguration. When no 'beans' property is set, all Spring beans in the context will be available.**

    <bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
      ...
      <property name="beans">
        <map>
          <entry key="printer" value-ref="printer" />
        </map>
      </property>
    </bean>

    <bean id="printer" class="org.flowable.examples.spring.Printer" />

Now the exposed beans can be used in expressions: for example, the SpringTransactionIntegrationTest hello.bpmn20.xml shows how a method on a Spring bean can be invoked using a UEL method expression:

    <definitions id="definitions">

      <process id="helloProcess">

        <startEvent id="start" />
        <sequenceFlow id="flow1" sourceRef="start" targetRef="print" />

        <serviceTask id="print" flowable:expression="#{printer.printMessage()}" />
        <sequenceFlow id="flow2" sourceRef="print" targetRef="end" />

        <endEvent id="end" />

      </process>

    </definitions>

Where Printer looks like this:

    public class Printer {

      public void printMessage() {
        System.out.println("hello world");
      }
    }

And the Spring bean configuration (also shown above) looks like this:

    <beans>
      ...

      <bean id="printer" class="org.flowable.examples.spring.Printer" />

    </beans>

## Automatic resource deployment

Spring integration also has a special feature for deploying resources. In the process engine configuration, you can specify a set of resources. When the process engine is created, all those resources will be scanned and deployed. There is filtering in place that prevents duplicate deployments. Only when the resources have actually changed will new deployments be deployed to the Flowable DB. This makes sense in a lot of use cases, where the Spring container is rebooted frequently (for example, testing).

Here’s an example:

    <bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
      ...
      <property name="deploymentResources"
        value="classpath*:/org/flowable/spring/test/autodeployment/autodeploy.*.bpmn20.xml" />
    </bean>

    <bean id="processEngine" class="org.flowable.spring.ProcessEngineFactoryBean">
      <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

By default, the configuration above will group all of the resources matching the filter into a single deployment to the Flowable engine. The duplicate filtering to prevent re-deployment of unchanged resources applies to the whole deployment. In some cases, this may not be what you want. For instance, if you deploy a set of process resources this way and only a single process definition in those resources has changed, the deployment as a whole will be considered new and all of the process definitions in that deployment will be re-deployed, resulting in new versions of each of the process definitions, even though only one was actually changed.

To be able to customize the way deployments are determined, you can specify an additional property in the SpringProcessEngineConfiguration, deploymentMode. This property defines the way deployments will be determined from the set of resources that match the filter. There are 3 values that are supported by default for this property:

-   default: Group all resources into a single deployment and apply duplicate filtering to that deployment. This is the default value and it will be used if you don’t specify a value.

-   single-resource: Create a separate deployment for each individual resource and apply duplicate filtering to that deployment. This is the value you would use to have each process definition be deployed separately and only create a new process definition version if it has changed.

-   resource-parent-folder: Create a separate deployment for resources that share the same parent folder and apply duplicate filtering to that deployment. This value can be used to create separate deployments for most resources, but still be able to group some by placing them in a shared folder. Here’s an example of how to specify the single-resource configuration for deploymentMode:



    <bean id="processEngineConfiguration"
        class="org.flowable.spring.SpringProcessEngineConfiguration">
      ...
      <property name="deploymentResources" value="classpath*:/flowable/*.bpmn" />
      <property name="deploymentMode" value="single-resource" />
    </bean>

In addition to using the values listed above for deploymentMode, you may require customized behavior towards determining deployments. If so, you can create a subclass of SpringProcessEngineConfiguration and override the getAutoDeploymentStrategy(String deploymentMode) method. This method determines which deployment strategy is used for a certain value of the deploymentMode configuration.

## Unit testing

When integrating with Spring, business processes can be tested very easily using the standard [Flowable testing facilities](bpmn/ch04-API.md#unit-testing).
The following examples show how a business process is tested in typical Spring-based JUnit Jupiter test:

**JUnit 5 test.**

    @ExtendWith(FlowableSpringExtension.class)
    @SpringJUnitConfig(SpringJunitJupiterTest.TestConfiguration.class)
    public class MyBusinessProcessTest {

      @Autowired
      private RuntimeService runtimeService;

      @Autowired
      private TaskService taskService;

      @Test
      @Deployment
      void simpleProcessTest() {
        runtimeService.startProcessInstanceByKey("simpleProcess");
        Task task = taskService.createTaskQuery().singleResult();
        assertEquals("My Task", task.getName());

        taskService.complete(task.getId());
        assertEquals(0, runtimeService.createProcessInstanceQuery().count());

      }
    }

Using the FlowableSpringExtension allows the usage of the Deployment annotation.

## JPA with Hibernate 4.2.x

When using Hibernate 4.2.x JPA in service task or listener logic in the Flowable engine, an additional dependency to Spring ORM is needed. This is not needed for Hibernate 4.1.x or earlier. The following dependency should be added:

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>

---

### Docusaurus Docs Bpmn Ch05a Spring Boot (`docs/docusaurus/docs/bpmn/ch05a-Spring-Boot.md`)

---
id: ch05a-Spring-Boot
title: Spring Boot
---

Spring Boot is an application framework which, according to [its website](http://projects.spring.io/spring-boot/), *makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run". It takes an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration*.

For more information on Spring Boot, see [<http://projects.spring.io/spring-boot/>](http://projects.spring.io/spring-boot/)

The Spring Boot - Flowable integration has been developed together with Spring committers.

## Compatibility

Flowable supports Spring Boot 4.x.

## Getting started

Spring Boot is all about convention over configuration.
To get started, you would need to create a Spring Boot project.
The easiest way to do this would be to create a project via [start.spring.io](https://start.spring.io/).
For example create a project with web and h2 dependencies.
Then in the created project simply add the *flowable-spring-boot-starter* or *flowable-spring-boot-starter-rest* dependency.
In case you don’t need all the engines see the other [Flowable starters](bpmn/ch05a-Spring-Boot.md#flowable-starters).
For example for Maven:

    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-spring-boot-starter</artifactId>
        <version>${flowable.version}</version>
    </dependency>

That’s all that’s needed. This dependency will transitively add the correct Flowable dependencies to the classpath.
You can now run your Spring Boot application:

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication(proxyBeanMethods = false)
    public class MyApplication {

        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }

    }

You will see an output like this:


.   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
'  |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/

:: Spring Boot ::                (v4.0.3)

2026-03-16T22:21:06.576+01:00  INFO 43702 --- [           main] com.example.demo.Application             : Starting Application using Java 25 with PID 43702 (/Users/filiphr/Downloads/demo 31/target/classes started by filiphr in /Users/filiphr/Downloads/demo 31)
2026-03-16T22:21:06.578+01:00  INFO 43702 --- [           main] com.example.demo.Application             : No active profile set, falling back to 1 default profile: "default"
2026-03-16T22:21:07.054+01:00  INFO 43702 --- [           main] o.s.boot.tomcat.TomcatWebServer          : Tomcat initialized with port 8080 (http)
2026-03-16T22:21:07.063+01:00  INFO 43702 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2026-03-16T22:21:07.063+01:00  INFO 43702 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/11.0.18]
2026-03-16T22:21:07.091+01:00  INFO 43702 --- [           main] b.w.c.s.WebApplicationContextInitializer : Root WebApplicationContext: initialization completed in 492 ms
2026-03-16T22:21:07.267+01:00  INFO 43702 --- [           main] o.f.s.b.app.AppEngineAutoConfiguration   : No deployment resources were found for autodeployment
2026-03-16T22:21:07.313+01:00  INFO 43702 --- [           main] o.f.s.b.ProcessEngineAutoConfiguration   : No deployment resources were found for autodeployment
2026-03-16T22:21:07.323+01:00  INFO 43702 --- [           main] o.f.c.e.i.a.DefaultAsyncTaskExecutor     : Creating thread pool queue of size 100
2026-03-16T22:21:07.324+01:00  INFO 43702 --- [           main] o.f.c.e.i.a.DefaultAsyncTaskExecutor     : Creating thread factory with naming pattern flowable-async-task-invoker-%d
2026-03-16T22:21:07.324+01:00  INFO 43702 --- [           main] o.f.c.e.i.a.DefaultAsyncTaskExecutor     : Creating executor service with corePoolSize 8, maxPoolSize 8 and keepAliveTime 5000
2026-03-16T22:21:07.361+01:00  INFO 43702 --- [           main] o.f.s.b.c.CmmnEngineAutoConfiguration    : No deployment resources were found for autodeployment
2026-03-16T22:21:07.385+01:00  INFO 43702 --- [           main] o.f.s.b.dmn.DmnEngineAutoConfiguration   : No deployment resources were found for autodeployment
2026-03-16T22:21:07.398+01:00  INFO 43702 --- [           main] o.f.s.b.e.EventRegistryAutoConfiguration : No deployment resources were found for autodeployment
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Found 5 Engine Configurators in total:
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : class org.flowable.engine.spring.configurator.SpringProcessEngineConfigurator (priority:50000)
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : class org.flowable.eventregistry.spring.configurator.SpringEventRegistryConfigurator (priority:100000)
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : class org.flowable.idm.spring.configurator.SpringIdmEngineConfigurator (priority:150000)
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : class org.flowable.dmn.spring.configurator.SpringDmnEngineConfigurator (priority:200000)
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : class org.flowable.cmmn.spring.configurator.SpringCmmnEngineConfigurator (priority:500000)
2026-03-16T22:21:07.420+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing beforeInit() of class org.flowable.engine.spring.configurator.SpringProcessEngineConfigurator (priority:50000)
2026-03-16T22:21:07.436+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing beforeInit() of class org.flowable.eventregistry.spring.configurator.SpringEventRegistryConfigurator (priority:100000)
2026-03-16T22:21:07.438+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing beforeInit() of class org.flowable.idm.spring.configurator.SpringIdmEngineConfigurator (priority:150000)
2026-03-16T22:21:07.439+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing beforeInit() of class org.flowable.dmn.spring.configurator.SpringDmnEngineConfigurator (priority:200000)
2026-03-16T22:21:07.441+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing beforeInit() of class org.flowable.cmmn.spring.configurator.SpringCmmnEngineConfigurator (priority:500000)
2026-03-16T22:21:07.454+01:00  INFO 43702 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2026-03-16T22:21:07.547+01:00  INFO 43702 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:09ef9a86-17d4-4411-bb28-88c57d6da066 user=SA
2026-03-16T22:21:07.548+01:00  INFO 43702 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2026-03-16T22:21:07.968+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing configure() of class org.flowable.engine.spring.configurator.SpringProcessEngineConfigurator (priority:50000)
2026-03-16T22:21:08.032+01:00  INFO 43702 --- [           main] o.f.engine.impl.ProcessEngineImpl        : ProcessEngine default created
2026-03-16T22:21:08.032+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing configure() of class org.flowable.eventregistry.spring.configurator.SpringEventRegistryConfigurator (priority:100000)
2026-03-16T22:21:08.038+01:00  INFO 43702 --- [           main] o.f.e.impl.EventRegistryEngineImpl       : EventRegistryEngine default created
2026-03-16T22:21:08.039+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing configure() of class org.flowable.idm.spring.configurator.SpringIdmEngineConfigurator (priority:150000)
2026-03-16T22:21:08.041+01:00  INFO 43702 --- [           main] o.f.idm.engine.impl.IdmEngineImpl        : IdmEngine default created
2026-03-16T22:21:08.042+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing configure() of class org.flowable.dmn.spring.configurator.SpringDmnEngineConfigurator (priority:200000)
2026-03-16T22:21:08.047+01:00  INFO 43702 --- [           main] o.f.dmn.engine.impl.DmnEngineImpl        : DmnEngine default created
2026-03-16T22:21:08.047+01:00  INFO 43702 --- [           main] o.f.a.s.SpringAppEngineConfiguration     : Executing configure() of class org.flowable.cmmn.spring.configurator.SpringCmmnEngineConfigurator (priority:500000)
2026-03-16T22:21:08.072+01:00  INFO 43702 --- [           main] o.f.cmmn.engine.impl.CmmnEngineImpl      : CmmnEngine default created
2026-03-16T22:21:08.085+01:00  INFO 43702 --- [           main] o.f.c.e.impl.db.CommonDbSchemaManager    : performing create on common with resource org/flowable/common/db/create/flowable.h2.create.common.sql
2026-03-16T22:21:08.124+01:00  INFO 43702 --- [           main] o.f.a.engine.impl.db.AppDbSchemaManager  : performing create on app with resource org/flowable/app/db/create/flowable.h2.create.app.sql
2026-03-16T22:21:08.129+01:00  INFO 43702 --- [           main] o.f.e.impl.db.ProcessDbSchemaManager     : performing create on engine with resource org/flowable/db/create/flowable.h2.create.engine.sql
2026-03-16T22:21:08.145+01:00  INFO 43702 --- [           main] o.f.e.impl.db.ProcessDbSchemaManager     : performing create on history with resource org/flowable/db/create/flowable.h2.create.history.sql
2026-03-16T22:21:08.148+01:00  INFO 43702 --- [           main] o.f.d.engine.impl.db.DmnDbSchemaManager  : performing create on dmn with resource org/flowable/dmn/db/create/flowable.h2.create.dmn.sql
2026-03-16T22:21:08.150+01:00  INFO 43702 --- [           main] o.f.c.e.impl.db.CmmnDbSchemaManager      : performing create on cmmn with resource org/flowable/cmmn/db/create/flowable.h2.create.cmmn.sql
2026-03-16T22:21:08.156+01:00  INFO 43702 --- [           main] o.f.i.engine.impl.db.IdmDbSchemaManager  : performing create on identity with resource org/flowable/idm/db/create/flowable.h2.create.identity.sql
2026-03-16T22:21:08.160+01:00  INFO 43702 --- [           main] o.f.e.impl.db.EventDbSchemaManager       : performing create on eventregistry with resource org/flowable/eventregistry/db/create/flowable.h2.create.eventregistry.sql
2026-03-16T22:21:08.162+01:00  INFO 43702 --- [           main] o.f.app.engine.impl.AppEngineImpl        : AppEngine default created
2026-03-16T22:21:08.186+01:00  INFO 43702 --- [           main] o.f.e.impl.cmd.ValidateV5EntitiesCmd     : Total of v5 deployments found: 0
2026-03-16T22:21:08.259+01:00  INFO 43702 --- [           main] o.f.j.s.i.a.AbstractAsyncExecutor        : Starting up the async job executor [org.flowable.spring.job.service.SpringAsyncExecutor] for engine cmmn
2026-03-16T22:21:08.267+01:00  INFO 43702 --- [       Thread-3] o.f.j.s.i.a.ResetExpiredJobsRunnable     : starting to reset expired jobs for engine cmmn
2026-03-16T22:21:08.268+01:00  INFO 43702 --- [           main] o.f.j.s.i.a.AbstractAsyncExecutor        : Starting up the async job executor [org.flowable.spring.job.service.SpringAsyncExecutor] for engine bpmn
2026-03-16T22:21:08.268+01:00  INFO 43702 --- [       Thread-2] o.f.j.s.i.a.AcquireTimerJobsRunnable     : starting to acquire async jobs due for engine cmmn
2026-03-16T22:21:08.268+01:00  INFO 43702 --- [       Thread-1] o.f.j.s.i.a.AcquireAsyncJobsDueRunnable  : starting to acquire async jobs due for engine cmmn
2026-03-16T22:21:08.268+01:00  INFO 43702 --- [       Thread-4] o.f.j.s.i.a.AcquireAsyncJobsDueRunnable  : starting to acquire async jobs due for engine bpmn
2026-03-16T22:21:08.268+01:00  INFO 43702 --- [       Thread-5] o.f.j.s.i.a.AcquireTimerJobsRunnable     : starting to acquire async jobs due for engine bpmn
2026-03-16T22:21:08.268+01:00  INFO 43702 --- [       Thread-6] o.f.j.s.i.a.ResetExpiredJobsRunnable     : starting to reset expired jobs for engine bpmn
2026-03-16T22:21:08.287+01:00  INFO 43702 --- [           main] o.s.boot.tomcat.TomcatWebServer          : Tomcat started on port 8080 (http) with context path '/'
2026-03-16T22:21:08.290+01:00  INFO 43702 --- [           main] com.example.demo.Application             : Started Application in 1.885 seconds (process running for 2.062)

So, by just adding the dependency to the classpath and using the *@SpringBootApplication* annotation a lot has happened behind the scenes:

-   An in-memory datasource is created automatically (because the H2 driver is on the classpath) and passed to the Flowable process engine configuration

-   A Flowable ProcessEngine, CmmnEngine, DmnEngine and IdmEngine beans have been created and exposed

-   All the Flowable services are exposed as Spring beans

-   The Spring Job Executor is created

Also:

-   Any BPMN 2.0 process definitions in the *processes* folder will be automatically deployed. Create a folder *processes* and add a dummy process definition (named *one-task-process.bpmn20.xml*) to this folder. The content of this file is shown below.

-   Any CMMN 1.1 case definitions in the *cases* folder will be automatically deployed.

-   Any DMN 1.1 dmn definitions in the *dmn* folder will be automatically deployed.

The XML content of the process definition is shown below. Notice that, for the moment, we are hard-coding an assignee called "kermit" to the user task. We’ll come back to this later.

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions
            xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
            xmlns:flowable="http://flowable.org/bpmn"
            targetNamespace="Examples">

        <process id="oneTaskProcess" name="The One Task Process">
            <startEvent id="theStart" />
            <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
            <userTask id="theTask" name="my task" flowable:assignee="kermit" />
            <sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
            <endEvent id="theEnd" />
        </process>

    </definitions>

Also, add following code lines to test if the deployment actually worked. The *CommandLineRunner* is a special kind of Spring bean that is executed when the application boots:

    @SpringBootApplication(proxyBeanMethods = false)
    public class MyApplication {

        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }

        @Bean
        public CommandLineRunner init(final RepositoryService repositoryService,
                                      final RuntimeService runtimeService,
                                      final TaskService taskService) {

            return new CommandLineRunner() {
                @Override
                public void run(String... strings) throws Exception {
                    System.out.println("Number of process definitions : "
                        + repositoryService.createProcessDefinitionQuery().count());
                    System.out.println("Number of tasks : " + taskService.createTaskQuery().count());
                    runtimeService.startProcessInstanceByKey("oneTaskProcess");
                    System.out.println("Number of tasks after process start: "
                        + taskService.createTaskQuery().count());
                }
            };
        }
    }

The output expected will be:

    Number of process definitions : 1
    Number of tasks : 0
    Number of tasks after process start : 1

## Changing the database and connection pool

As stated above, Spring Boot is about convention over configuration. By default, by having only H2 on the classpath, it created an in-memory datasource and passed that to the Flowable process engine configuration.

To change the datasource, simply add the database driver dependencies and provide the URL to the database.
For example, to switch to a MySQL database:

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/flowable-spring-boot?characterEncoding=UTF-8
    spring.datasource.username=flowable
    spring.datasource.password=flowable

Remove H2 from the Maven dependencies and add the MySQL driver to the classpath:

    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>9.6.0</version>
    </dependency>

When the app is now booted up, you’ll see it uses MySQL as database (and the HikariCP connection pooling framework):

    org.flowable.engine.impl.db.DbSqlSession   : performing create on engine with resource org/flowable/db/create/flowable.mysql.create.engine.sql
    org.flowable.engine.impl.db.DbSqlSession   : performing create on history with resource org/flowable/db/create/flowable.mysql.create.history.sql
    org.flowable.engine.impl.db.DbSqlSession   : performing create on identity with resource org/flowable/db/create/flowable.mysql.create.identity.sql

When you reboot the application multiple times, you’ll see the number of tasks go up (the H2 in-memory database does not survive a shutdown, MySQL does).

For more information about how to configure the datasource have a look in [Configure a DataSource](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-configure-datasource) in the Spring Boot reference guide.

## REST support

Often, a REST API is used on top of the embedded Flowable engine (interacting with the different services in a company). Spring Boot makes this really easy. Add following dependency to the classpath:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>${spring.boot.version}</version>
    </dependency>

Create a new class, a Spring service and create two methods: one to start our process and one to get a task list for a given assignee. We simply wrap Flowable calls here, but in real-life scenarios this will be more complex.

    @Service
    public class MyService {

        @Autowired
        private RuntimeService runtimeService;

        @Autowired
        private TaskService taskService;

        @Transactional
        public void startProcess() {
            runtimeService.startProcessInstanceByKey("oneTaskProcess");
        }

        @Transactional
        public List<Task> getTasks(String assignee) {
            return taskService.createTaskQuery().taskAssignee(assignee).list();
        }

    }

We can now create a REST endpoint by annotating a class with *@RestController*. Here, we simply delegate to the service defined above.

    @RestController
    public class MyRestController {

        @Autowired
        private MyService myService;

        @PostMapping(value="/process")
        public void startProcessInstance() {
            myService.startProcess();
        }

        @RequestMapping(value="/tasks", method= RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
        public List<TaskRepresentation> getTasks(@RequestParam String assignee) {
            List<Task> tasks = myService.getTasks(assignee);
            List<TaskRepresentation> dtos = new ArrayList<TaskRepresentation>();
            for (Task task : tasks) {
                dtos.add(new TaskRepresentation(task.getId(), task.getName()));
            }
            return dtos;
        }

        static class TaskRepresentation {

            private String id;
            private String name;

            public TaskRepresentation(String id, String name) {
                this.id = id;
                this.name = name;
            }

            public String getId() {
                return id;
            }
            public void setId(String id) {
                this.id = id;
            }
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }

        }

    }

Both the *@Service* and the *@RestController* will be found by the automatic component scan for a Spring Boot application.
Run the application class again. We can now interact with the REST API, for example, by using cURL:

    curl http://localhost:8080/tasks?assignee=kermit
    []

    curl -X POST  http://localhost:8080/process
    curl http://localhost:8080/tasks?assignee=kermit
    [{"id":"10004","name":"my task"}]

As can be seen, we are referring to the assignee, "kermit", which was hard-coded into the process definition XML earlier. We’ll change this later on to allow the assignee to be set when the workflow instance is started.

## JPA support

To add JPA support for Flowable in Spring Boot, add following dependency:

    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-spring-boot-starter</artifactId>
        <version>${flowable.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>${spring-boot.version</version>
    </dependency>

This will add in the Spring configuration and beans for using JPA. By default, the JPA provider will be Hibernate.

Let’s create a simple Entity class:

    @Entity
    class Person {

        @Id
        @GeneratedValue
        private Long id;

        private String username;

        private String firstName;

        private String lastName;

        private Date birthDate;

        public Person() {
        }

        public Person(String username, String firstName, String lastName, Date birthDate) {
            this.username = username;
            this.firstName = firstName;
            this.lastName = lastName;
            this.birthDate = birthDate;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        public Date getBirthDate() {
            return birthDate;
        }

        public void setBirthDate(Date birthDate) {
            this.birthDate = birthDate;
        }
    }

By default, when not using an in-memory database, the tables won’t be created automatically. Create a file *application.properties* on the classpath and add following property:

    spring.jpa.hibernate.ddl-auto=update

Add following class:

    @Repository
    public interface PersonRepository extends JpaRepository<Person, Long> {

        Person findByUsername(String username);
    }

This is a Spring repository, which offers CRUD out of the box. We add the method to find a Person by username. Spring will automatically implement this based on conventions (typically, the property names used).

We now enhance our service further:

-   by adding *@Transactional* to the class. Note that by adding the JPA dependency above, the DataSourceTransactionManager which we were using before is now automatically swapped out by a JpaTransactionManager.

-   The *startProcess* now gets an assignee username passed in, which is used to look up the Person, and put the Person JPA object as a process variable in the process instance.

-   A method to create Dummy users is added. This is used in the CommandLineRunner to populate the database.



    @Service
    @Transactional
    public class MyService {

        @Autowired
        private RuntimeService runtimeService;

        @Autowired
        private TaskService taskService;

        @Autowired
        private PersonRepository personRepository;

        public void startProcess(String assignee) {

            Person person = personRepository.findByUsername(assignee);

            Map<String, Object> variables = new HashMap<String, Object>();
            variables.put("person", person);
            runtimeService.startProcessInstanceByKey("oneTaskProcess", variables);
        }

        public List<Task> getTasks(String assignee) {
            return taskService.createTaskQuery().taskAssignee(assignee).list();
        }

        public void createDemoUsers() {
            if (personRepository.findAll().size() == 0) {
                personRepository.save(new Person("jbarrez", "Joram", "Barrez", new Date()));
                personRepository.save(new Person("trademakers", "Tijs", "Rademakers", new Date()));
            }
        }

    }

The CommandLineRunner now looks like:

    @Bean
    public CommandLineRunner init(final MyService myService) {

        return new CommandLineRunner() {
            public void run(String... strings) throws Exception {
                myService.createDemoUsers();
            }
        };
    }

The RestController is also modified slightly to incorporate the changes above (only showing new methods) and the HTTP POST now has a body that contains the assignee username:

    @RestController
    public class MyRestController {

        @Autowired
        private MyService myService;

        @PostMapping(value="/process")
        public void startProcessInstance(@RequestBody StartProcessRepresentation startProcessRepresentation) {
            myService.startProcess(startProcessRepresentation.getAssignee());
        }

       ...

        static class StartProcessRepresentation {

            private String assignee;

            public String getAssignee() {
                return assignee;
            }

            public void setAssignee(String assignee) {
                this.assignee = assignee;
            }
        }

And finally, to try out the Spring-JPA-Flowable integration, we assign the task using the ID of the Person JPA object in the process definition:

    <userTask id="theTask" name="my task" flowable:assignee="${person.id}"/>

This replaces the hard-coded recipient, "kermit", which we had initially set.

We can now start a new process instance, providing the user name in the POST body:

    curl -H "Content-Type: application/json" -d '{"assignee" : "jbarrez"}' http://localhost:8080/process

And the task list is now fetched using the person ID:

    curl http://localhost:8080/tasks?assignee=1

    [{"id":"12505","name":"my task"}]

## Flowable Actuator Endpoints

Flowable provides a Spring Boot Actuator Endpoint that exposes information for the Processes that are running.
By default, the `flowable` endpoint is mapped to `/actuator/flowable`.
Spring Boot by default only exposes a few endpoints to the web (e.g.: In `spring-boot-starter-actuator:2.5.4` , Spring Boot by default only exposes the `health` endpoint to the web. For more information about the endpoints exposed to the web by default, see [https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.exposing](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.exposing) ). In order to use the `flowable` endpoint through the web, you need to add `management.endpoints.web.exposure.include=flowable` to your `application.properties` (Note: The `org.flowable.spring.boot.EndpointAutoConfiguration` class does not use the `@ConditionalOnAvailableEndpoint` annotation to check whether the `flowable` endpoint is both enabled and exposed like the `HealthEndpointAutoConfiguration` class. So the only thing you need to do to use the `flowable` endpoint through the web is to add `management.endpoints.web.exposure.include=flowable` or `management.endpoints.web.exposure.include=*` to your configuration file.).

In order to make enable Actuator endpoints you need to add a dependency on Actuator, e.g. by using {sc-flowable-starter}/flowable-spring-boot-starter-actuator/pom.xml\[flowable-spring-boot-starter-actuator\].

`curl http://localhost:8080/actuator/flowable`

    {
      "completedTaskCountToday": 0,
      "deployedProcessDefinitions": [
        "oneTaskProcess (v1)"
      ],
      "processDefinitionCount": 1,
      "cachedProcessDefinitionCount": 0,
      "runningProcessInstanceCount": {
        "oneTaskProcess (v1)": 0
      },
      "completedTaskCount": 2,
      "completedActivities": 3,
      "completedProcessInstanceCount": {
        "oneTaskProcess (v1)": 0
      },
      "openTaskCount": 0
    }

For more information about Spring Boot Actuator see [Production Ready Endpoint](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html) in the Spring Boot reference documentation.

## Flowable Info Contributor

Flowable also provides a Spring Boot `InfoContributor` which looks like:

`curl http://localhost:8080/actuator/info`

    {
      "flowable": {
        "version": "6.6.0"
      }
    }

## Flowable Application Properties

The Flowable auto configuration is leveraging the Spring Boot properties and configuration mechanism.
See [Properties and Configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html) in the Spring Boot reference guide.

Here is a list of configuration properties that the Flowable Spring Boot support consumes.

    # ===================================================================
    # Common Flowable Spring Boot Properties
    #
    # This sample file is provided as a guideline. Do NOT copy it in its
    # entirety to your own application.            ^^^
    # ===================================================================

    # Core (Process) https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/FlowableProperties.java
    flowable.check-process-definitions=true # Whether process definitions need to be auto deployed.
    flowable.custom-mybatis-mappers= # The FQN of custom Mybatis mappers that need to be added to the engine.
    flowable.custom-mybatis-x-m-l-mappers= # The location of the custom Mybatis XML Mappers that need to be added to the engine.
    flowable.database-schema= # In some situations you want to set the schema to use for table checks / generation if the database metadata doesn't return that correctly.
    flowable.database-schema-update=true # The strategy that should be used for the database schema.
    flowable.db-history-used=true # Whether db history should be used.
    flowable.deployment-name=SpringBootAutoDeployment # The name of the auto deployment.
    flowable.history-level=audit # The history level that needs to be used.
    flowable.process-definition-location-prefix=classpath*:/processes/ # The folder in which processes need to be searched for auto deployment.
    flowable.process-definition-location-suffixes=**.bpmn20.xml,**.bpmn # The suffixes (extensions) of the files that needs to be deployed from the 'processDefinitionLocationPrefix' location.

    # Process https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/process/FlowableProcessProperties.java
    flowable.process.definition-cache-limit=-1 # The maximum amount of process definitions available in the process definition cache. Per default it is -1 (all process definitions).
    flowable.process.enable-safe-xml=true # Enables extra checks on the BPMN xml that is parsed. Unfortunately, this feature is not available on some platforms, hence you need to disable if your platform does not allow the use of StaxSource during XML parsing.
    flowable.process.servlet.load-on-startup=-1 # Load on startup of the Process dispatcher servlet.
    flowable.process.servlet.name=Flowable BPMN Rest API # The name of the Process servlet.
    flowable.process.servlet.path=/process-api # The context path for the Process rest servlet.

    # Process Async Executor
    flowable.process.async-executor-activate=true # Whether the async executor should be activated.
    flowable.process.async.executor.async-job-lock-time=PT5M # The amount of time an async job is locked when acquired by the async executor. During this period of time, no other async executor will try to acquire and lock this job.
    flowable.process.async.executor.default-async-job-acquire-wait-time=PT10S # The time the async job acquisition thread will wait to execute the next acquirement query. This happens when no new async jobs were found or when less async jobs have been fetched. Default value = 10 seconds.
    flowable.process.async.executor.default-queue-size-full-wait-time=PT5S # The time the async job (both timer and async continuations) acquisition thread will wait when the queue is full to execute the next query.
    flowable.process.async.executor.default-timer-job-acquire-wait-time=PT10S # The time the timer job acquisition thread will wait to execute the next acquirement query. This happens when no new timer jobs were found or when less async jobs have been fetched. Default value = 10 seconds.
    flowable.process.async.executor.max-async-jobs-due-per-acquisition=1 # ???
    flowable.process.async.executor.timer-lock-time=PT5M # The amount of time a timer job is locked when acquired by the async executor. During this period of time, no other async executor will try to acquire and lock this job.


    # CMMN https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/cmmn/FlowableCmmnProperties.java
    flowable.cmmn.deploy-resources=true # Whether to perform deployment of resources, default is 'true'.
    flowable.cmmn.deployment-name=SpringBootAutoDeployment # The name of the deployment for the CMMN resources.
    flowable.cmmn.enable-safe-xml=true # Enables extra checks on the DMN xml that is parsed. Unfortunately, this feature is not available on some platforms, hence you need to disable if your platform does not allow the use of StaxSource during XML parsing.
    flowable.cmmn.enabled=true # Whether the CMMN engine needs to be started.
    flowable.cmmn.resource-location=classpath*:/cases/ # The location where the CMMN resources are located.
    flowable.cmmn.resource-suffixes=**.cmmn,**.cmmn11,**.cmmn.xml,**.cmmn11.xml # The suffixes for the resources that need to be scanned.
    flowable.cmmn.servlet.load-on-startup=-1 # Load on startup of the CMMN dispatcher servlet.
    flowable.cmmn.servlet.name=Flowable CMMN Rest API # The name of the CMMN servlet.
    flowable.cmmn.servlet.path=/cmmn-api # The context path for the CMMN rest servlet.

    # CMMN Async Executor
    flowable.cmmn.async-executor-activate=true # Whether the async executor should be activated.
    flowable.cmmn.async.executor.async-job-lock-time=PT5M # The amount of time an async job is locked when acquired by the async executor. During this period of time, no other async executor will try to acquire and lock this job.
    flowable.cmmn.async.executor.default-async-job-acquire-wait-time=PT10S # The time the async job acquisition thread will wait to execute the next acquirement query. This happens when no new async jobs were found or when less async jobs have been fetched. Default value = 10 seconds.
    flowable.cmmn.async.executor.default-queue-size-full-wait-time=PT5S # The time the async job (both timer and async continuations) acquisition thread will wait when the queue is full to execute the next query.
    flowable.cmmn.async.executor.default-timer-job-acquire-wait-time=PT10S # The time the timer job acquisition thread will wait to execute the next acquirement query. This happens when no new timer jobs were found or when less async jobs have been fetched. Default value = 10 seconds.
    flowable.cmmn.async.executor.max-async-jobs-due-per-acquisition=1 # ???
    flowable.cmmn.async.executor.timer-lock-time=PT5M # The amount of time a timer job is locked when acquired by the async executor. During this period of time, no other async executor will try to acquire and lock this job.

    # DMN https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/dmn/FlowableDmnProperties.java
    flowable.dmn.deploy-resources=true # Whether to perform deployment of resources, default is 'true'.
    flowable.dmn.deployment-name=SpringBootAutoDeployment # The name of the deployment for the dmn resources.
    flowable.dmn.enable-safe-xml=true # Enables extra checks on the DMN xml that is parsed. Unfortunately, this feature is not available on some platforms, hence you need to disable if your platform does not allow the use of StaxSource during XML parsing.
    flowable.dmn.enabled=true # Whether the dmn engine needs to be started.
    flowable.dmn.history-enabled=true # Whether the history for the DMN engine should be enabled.
    flowable.dmn.resource-location=classpath*:/dmn/ # The location where the dmn resources are located.
    flowable.dmn.resource-suffixes=**.dmn,**.dmn.xml,**.dmn11,**.dmn11.xml # The suffixes for the resources that need to be scanned.
    flowable.dmn.servlet.load-on-startup=-1 # Load on startup of the DMN dispatcher servlet.
    flowable.dmn.servlet.name=Flowable DMN Rest API # The name of the DMN servlet.
    flowable.dmn.servlet.path=/dmn-api # The context path for the DMN rest servlet.
    flowable.dmn.strict-mode=true # Set this to false if you want to ignore the decision table hit policy validity checks to result in an failed decision table state. A result is that intermediate results created up to the point the validation error occurs are returned.

    # IDM https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/idm/FlowableIdmProperties.java
    flowable.idm.enabled=true # Whether the idm engine needs to be started.
    flowable.idm.password-encoder= # The type of the password encoder that needs to be used.
    flowable.idm.servlet.load-on-startup=-1 # Load on startup of the IDM dispatcher servlet.
    flowable.idm.servlet.name=Flowable IDM Rest API # The name of the IDM servlet.
    flowable.idm.servlet.path=/idm-api # The context path for the IDM rest servlet.

    # IDM Ldap https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/ldap/FlowableLdapProperties.java
    flowable.idm.ldap.attribute.email= # Name of the attribute that matches the user email.
    flowable.idm.ldap.attribute.first-name= # Name of the attribute that matches the user first name.
    flowable.idm.ldap.attribute.group-id= # Name of the attribute that matches the group id.
    flowable.idm.ldap.attribute.group-name= # Name of the attribute that matches the group name.
    flowable.idm.ldap.attribute.group-type= # Name of the attribute that matches the group type.
    flowable.idm.ldap.attribute.last-name= # Name of the attribute that matches the user last name.
    flowable.idm.ldap.attribute.user-id= # Name of the attribute that matches the user id.
    flowable.idm.ldap.base-dn= # The base 'distinguished name' (DN) from which the searches for users and groups are started.
    flowable.idm.ldap.cache.group-size=-1 # Allows to set the size of the {@link org.flowable.ldap.LDAPGroupCache}. This is an LRU cache that caches groups for users and thus avoids hitting the LDAP system each time the groups of a user needs to be known.
    flowable.idm.ldap.custom-connection-parameters= # Allows to set all LDAP connection parameters which do not have a dedicated setter. See for example http://docs.oracle.com/javase/tutorial/jndi/ldap/jndi.html for custom properties. Such properties are for example to configure connection pooling, specific security settings, etc.
    flowable.idm.ldap.enabled=false # Whether to enable LDAP IDM Service.
    flowable.idm.ldap.group-base-dn= # The base 'distinguished name' (DN) from which the searches for groups are started.
    flowable.idm.ldap.initial-context-factory=com.sun.jndi.ldap.LdapCtxFactory # The class name for the initial context factory.
    flowable.idm.ldap.password= # The password that is used to connect to the LDAP system.
    flowable.idm.ldap.port=-1 # The port on which the LDAP system is running.
    flowable.idm.ldap.query.all-groups= # The query that is executed when searching for all groups.
    flowable.idm.ldap.query.all-users= # The query that is executed when searching for all users.
    flowable.idm.ldap.query.groups-for-user= # The query that is executed when searching for the groups of a specific user.
    flowable.idm.ldap.query.user-by-full-name-like= # The query that is executed when searching for a user by full name.
    flowable.idm.ldap.query.user-by-id= # The query that is executed when searching for a user by userId.
    flowable.idm.ldap.query.group-by-id= # The query that is executed when searching for a specific group by groupId.
    flowable.idm.ldap.search-time-limit=0 # The timeout (in milliseconds) that is used when doing a search in LDAP. By default set to '0', which means 'wait forever'.
    flowable.idm.ldap.security-authentication=simple # The value that is used for the 'java.naming.security.authentication' property used to connect to the LDAP system.
    flowable.idm.ldap.server= # The server host on which the LDAP system can be reached. For example 'ldap://localhost'.
    flowable.idm.ldap.user= # The user id that is used to connect to the LDAP system.
    flowable.idm.ldap.user-base-dn= # The base 'distinguished name' (DN) from which the searches for users are started.

    # Flowable Mail https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/FlowableMailProperties.java
    flowable.mail.server.default-from=flowable@localhost # The default from address that needs to be used when sending emails.
    flowable.mail.server.force-to= # The force to address(es) that would be used when sending out emails. IMPORTANT: If this is set then all emails will be send to defined address(es) instead of the address configured in the MailActivity.
    flowable.mail.server.host=localhost # The host of the mail server.
    flowable.mail.server.password= # The password for the mail server authentication.
    flowable.mail.server.port=1025 # The port of the mail server.
    flowable.mail.server.ssl-port=1465 # The SSL port of the mail server.
    flowable.mail.server.use-ssl=false # Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS).
    flowable.mail.server.use-tls=false # Set or disable the STARTTLS encryption.
    flowable.mail.server.username= # The username that needs to be used for the mail server authentication. If empty no authentication would be used.

    # Flowable Http https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/FlowableHttpProperties.java
    flowable.http.user-system-properties=false # Whether to use system properties (e.g. http.proxyPort).
    flowable.http.connect-timeout=5s # Connect timeout for the http client
    flowable.http.socket-timeout=5s # Socket timeout for the http client
    flowable.http.connection-request-timeout=5s # Connection Request Timeout for the http client
    flowable.http.request-retry-limit=3 # Request retry limit for the http client
    flowable.http.disable-cert-verify=false # Whether to disable certificate validation for the http client

    # Flowable REST
    flowable.rest.app.cors.enabled=true # Whether to enable CORS requests at all. If false, the other properties have no effect
    flowable.rest.app.cors.allow-credentials=true # Whether to include credentials in a CORS request
    flowable.rest.app.cors.allowed-origins=* # Comma-separated URLs to accept CORS requests from
    flowable.rest.app.cors.allowed-headers=* # Comma-separated HTTP headers to allow in a CORS request
    flowable.rest.app.cors.allowed-methods=DELETE,GET,PATCH,POST,PUT # Comma-separated HTTP verbs to allow in a CORS request
    flowable.rest.app.cors.exposed-headers=* # Comma-separated list of headers to expose in CORS response

    # Actuator
    management.endpoint.flowable.cache.time-to-live=0ms # Maximum time that a response can be cached.
    management.endpoint.flowable.enabled=true # Whether to enable the flowable endpoint.


<table>
<caption>Deprecated properties</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Property name</th>
<th>Old Property</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>flowable.process.servlet.name</p></td>
<td><p>flowable.rest-api-servlet-name</p></td>
<td><p>Flowable BPMN Rest API</p></td>
<td><p>The name of the Process servlet.</p></td>
</tr>
<tr class="even">
<td><p>flowable.process.servlet.path</p></td>
<td><p>flowable.rest-api-mapping</p></td>
<td><p>/process-api</p></td>
<td><p>The context path for the Process rest servlet.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.host</p></td>
<td><p>flowable.mail-server-host</p></td>
<td><p>localhost</p></td>
<td><p>The host of the mail server.</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.password</p></td>
<td><p>flowable.mail-server-password</p></td>
<td><p>-</p></td>
<td><p>The password for the mail server authentication.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.port</p></td>
<td><p>flowable.mail-server-port</p></td>
<td><p>1025</p></td>
<td><p>The port of the mail server.</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.ssl-port</p></td>
<td><p>flowable.mail-server-ssl-port</p></td>
<td><p>1465</p></td>
<td><p>The SSL port of the mail server.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.use-ssl</p></td>
<td><p>flowable.mail-server-use-ssl</p></td>
<td><p>false</p></td>
<td><p>Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS).</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.use-tls</p></td>
<td><p>flowable.mail-server-use-tls</p></td>
<td><p>false</p></td>
<td><p>Set or disable the STARTTLS encryption.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.username</p></td>
<td><p>flowable.mail-server-user-name</p></td>
<td><p>-</p></td>
<td><p>The username that needs to be used for the mail server authentication.
If empty no authentication would be used.</p></td>
</tr>
<tr class="even">
<td><p>flowable.process.definition-cache-limit</p></td>
<td><p>flowable.process-definitions.cache.max</p></td>
<td><p>-1</p></td>
<td><p>The maximum amount of process definitions available in the process definition cache.
Per default it is -1 (all process definitions)</p></td>
</tr>
</tbody>
</table>

## Flowable Auto-configuration classes

Here is a list of all auto-configuration classes provided by Flowable, with links to documentation and source code.
Remember to also look at the conditions report in your application for more details of which features are switched on.
(To do so, start the app with --debug or -Ddebug or, in an Actuator application, use the conditions endpoint).

<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<thead>
<tr class="header">
<th>Configuration Class</th>
</tr>
</thead>
<tbody>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/cmmn/CmmnEngineAutoConfiguration.java">CmmnEngineAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/cmmn/CmmnEngineServicesAutoConfiguration.java">CmmnEngineServicesAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/dmn/DmnEngineAutoConfiguration.java">DmnEngineAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/dmn/DmnEngineServicesAutoConfiguration.java">DmnEngineServicesAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/EndpointAutoConfiguration.java">EndpointAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/actuate/info/FlowableInfoAutoConfiguration.java">FlowableInfoAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/ldap/FlowableLdapAutoConfiguration.java">FlowableLdapAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/idm/IdmEngineAutoConfiguration.java">IdmEngineAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/idm/IdmEngineServicesAutoConfiguration.java">IdmEngineServicesAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/ProcessEngineAutoConfiguration.java">ProcessEngineAutoConfiguration</a></p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/RestApiAutoConfiguration.java">RestApiAutoConfiguration</a></p></td>
</tr>
</tbody>
</table>

## Flowable Starters

Here is a list of the flowable spring boot starters.

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Starter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-cmmn/pom.xml">flowable-spring-boot-starter-cmmn</a></p></td>
<td><p>Contains the dependencies for booting the CMMN Engine in Standalone mode</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-cmmn-rest/pom.xml">flowable-spring-boot-starter-cmmn-rest</a></p></td>
<td><p>Contains the dependencies for booting the CMMN Engine in Standalone mode and starts its REST API</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-dmn/pom.xml">flowable-spring-boot-starter-dmn</a></p></td>
<td><p>Contains the dependencies for booting the DMN Engine in Standalone mode</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-dmn-rest/pom.xml">flowable-spring-boot-starter-dmn-rest</a></p></td>
<td><p>Contains the dependencies for booting the DMN Engine in Standalone mode and starts its REST API</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-process/pom.xml">flowable-spring-boot-starter-process</a></p></td>
<td><p>Contains the dependencies for booting the Process Engine in Standalone mode</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-process-rest/pom.xml">flowable-spring-boot-starter-process-rest</a></p></td>
<td><p>Contains the dependencies for booting the Process Engine in Standalone mode and starts its REST API</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter/pom.xml">flowable-spring-boot-starter</a></p></td>
<td><p>Contains the dependencies for booting all Flowable Engines (Process, CMMN, DMN, and IDM)</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-rest/pom.xml">flowable-spring-boot-starter-rest</a></p></td>
<td><p>Contains the dependencies for booting all Flowable Engines and their respective REST API</p></td>
</tr>
<tr>
<td><p><a href="https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-starter-actuator/pom.xml">flowable-spring-boot-starter-actuator</a></p></td>
<td><p>Contains the required dependencies for Spring Boot</p></td>
</tr>
</tbody>
</table>

## Using Liquibase

The Flowable engines are using Liquibase to manage the versioning of it’s tables.
This means that the `LiquibaseAutoConfiguration` from Spring Boot would automatically kick in.
However, if you are not using Liquibase then the application will not start and would throw an exception.
For this reason Flowable is setting `spring.liquibase.enabled` to `false`, which means that if you need to use Liquibase you have to explicitly enable it.

## Further Reading

Obviously, there is a lot about Spring Boot that hasn’t been touched upon yet, like very easy JTA integration or building a WAR file that can be run on major application servers. And there is a lot more to the Spring Boot integration:

-   Actuator support

-   Spring Integration support

-   Rest API integration: boot up the Flowable Rest API embedded within the Spring application

-   Spring Security support

## Advanced Configuration

### Customizing Engine Configuration

It’s possible to get a hold of the engine configuration by implementing the *org.flowable.spring.boot.EngineConfigurationConfigurer&lt;T&gt;* interface.
Where *T* is the Spring Type of the particular Engine Configuration.
This can be useful for advanced configuration settings or simply because a property has not been exposed (yet).
For example:

    public class MyConfigurer implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {

        public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
            // advanced configuration
        }

    }

By exposing an instance of this class as an *@Bean* in the Spring Boot configuration, the instance will be called before the process engine is fully created.

> **Tip**
>
> You can provide a custom implementation of a Flowable Service by using this. See https://github.com/flowable/flowable-engine/tree/main/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/ldap/FlowableLdapAutoConfiguration.java\[FlowableLdapAutoConfiguration\]

### Combining starters

In case you need only a combination of the engines then you can add only the required dependencies.
For example to use the Process, CMMN, and IDM engine and use LDAP you need to add the following dependencies:

    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-spring-boot-starter-process</artifactId>
        <version>${flowable.version}</version>
    </dependency>
    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-spring-boot-starter-cmmn</artifactId>
        <version>${flowable.version}</version>
    </dependency>
    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-ldap</artifactId>
        <version>${flowable.version}</version>
    </dependency>

### Configuring Async Executors

The Process and CMMN engines have dedicated `AsyncExecutor`(s) and they can be configured with the `flowable.{engine}.async.executor` property group.
Where `engine` is either `process` or `cmmn`.

The `AsyncExecutor`(s) per default share the same Spring `TaskExecutor` and `SpringRejectedJobsHandler`.
In case you want to provide a dedicated executor for each of the engines you need define a qualified bean with `@Process` and `@Cmmn`.

You can configure custom executors in the following way:

    @Configuration
    public class MyConfiguration {

        @Process 
        @Bean
        public TaskExecutor processTaskExecutor() {
            return new SimpleAsyncTaskExecutor();
        }

        @Cmmn 
        @Bean
        public TaskExecutor cmmnTaskExecutor() {
            return new SyncTaskExecutor();
        }
    }

-   The Async Executor for the Process Engine would use a `SimpleAsyncTaskExecutor`

-   The Async Executor for the CMMN Engine would use a `SyncTaskExecutor`

> **Important**
>
> If you define a custom `TaskExecutor` bean the Flowable creation of the bean is not triggered.
> Which means that if you define a bean qualified with `@Process` you have to define one with `@Cmmn` or `@Primary`, otherwise the Cmmn Async Executor will use the one for the Process

---

### Docusaurus Docs Bpmn Ch06 Deployment (`docs/docusaurus/docs/bpmn/ch06-Deployment.md`)

---
id: ch06-Deployment
title: Deployment
---

## Business archives

To deploy processes, they have to be wrapped in a business archive (BAR). A business archive is the unit of deployment to a Flowable engine. A business archive is equivalent to a ZIP file. It can contain BPMN 2.0 processes, form definitions, DMN rules and any other type of file. In general, a business archive contains a collection of named resources.

When a business archive is deployed, it is scanned for BPMN files with a .bpmn20.xml or .bpmn extension. Each of those will be processed and may contain multiple process definitions.
When the DMN engine is activated, .dmn files are also parsed, and with the form engine activated, .form files are handled.

> **Note**
>
> Java classes present in the business archive **will not be added to the classpath**. All custom classes used in process definitions in the business archive (for example, Java service tasks or event listener implementations) must be made available on the Flowable engine classpath in order to run the processes.

### Deploying programmatically

Deploying a business archive from a ZIP file can be done like this:

    String barFileName = "path/to/process-one.bar";
    ZipInputStream inputStream = new ZipInputStream(new FileInputStream(barFileName));

    repositoryService.createDeployment()
        .name("process-one.bar")
        .addZipInputStream(inputStream)
        .deploy();

It’s also possible to build a deployment from individual resources. See the javadocs for more details.

## External resources

Process definitions live in the Flowable database. These process definitions can reference delegation classes when using Service Tasks or execution listeners or Spring beans from the Flowable configuration file. These classes and the Spring configuration file have to be available to all process engines that may execute the process definitions.

### Java classes

All custom classes that are used in your process (for example, JavaDelegates used in Service Tasks or event-listeners, TaskListeners and so on) should be present on the engine’s classpath when an instance of the process is started.

During deployment of a business archive however, those classes don’t have to be present on the classpath. This means that your delegation classes don’t have to be on the classpath when deploying a new business archive with Ant, for example.

When you are using the demo setup and you want to add your custom classes, you should add a JAR containing your classes to the flowable-task or flowable-rest webapp lib. Don’t forget to include the dependencies of your custom classes (if any) as well. Alternatively, you can include your dependencies in the libraries directory of your Tomcat installation, ${tomcat.home}/lib.

### Using Spring beans from a process

When expressions or scripts use Spring beans, those beans have to be available to the engine when executing the process definition. If you are building your own webapp and you configure your process engine in your context as described in [the spring integration section](bpmn/ch05-Spring.md#spring-integration), that is straightforward. But bear in mind that you also should update the Flowable task and rest webapps with that context if you use it.

### Creating a single app

Instead of making sure that all process engines have all the delegation classes on their classpath and use the right Spring configuration, you may consider including the Flowable REST webapp inside your own webapp so that there is only a single ProcessEngine.

## Versioning of process definitions

BPMN doesn’t have a notion of versioning. That is actually good, because the executable BPMN process file will probably live in a version control system repository (such as Subversion, Git or Mercurial) as part of your development project. However, versions of process definitions are created in the engine as part of deployment. During deployment, Flowable will assign a version to the ProcessDefinition before it is stored in the Flowable DB.

For each process definition in a business archive, the following steps are performed to initialize the properties key, version, name and id:

-   The process definition id attribute in the XML file is used as the process definition key property.

-   The process definition name attribute in the XML file is used as the process definition name property. If the name attribute is not specified, then the id attribute is used as the name.

-   The first time a process with a particular key is deployed, version 1 is assigned. For all subsequent deployments of process definitions with the same key, the version will be set 1 higher than the highest currently deployed version. The key property is used to distinguish process definitions.

-   The id property is set to {processDefinitionKey}:{processDefinitionVersion}:{generated-id}, where generated-id is a unique number added to guarantee uniqueness of the process ID for the process definition caches in a clustered environment.

Take for example the following process

    <definitions id="myDefinitions" >
      <process id="myProcess" name="My important process" >
        ...

When deploying this process definition, the process definition in the database will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>myProcess:1:676</p></td>
<td><p>myProcess</p></td>
<td><p>My important process</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Suppose we now deploy an updated version of the same process (for example, changing some user tasks), but the id of the process definition remains the same. The process definition table will now contain the following entries:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>myProcess:1:676</p></td>
<td><p>myProcess</p></td>
<td><p>My important process</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>myProcess:2:870</p></td>
<td><p>myProcess</p></td>
<td><p>My important process</p></td>
<td><p>2</p></td>
</tr>
</tbody>
</table>

When the runtimeService.startProcessInstanceByKey("myProcess") is called, it will now use the process definition with version 2, as this is the latest version of the process definition.

Should we create a second process, as defined below and deploy this to Flowable, a third row will be added to the table.

    <definitions id="myNewDefinitions" >
      <process id="myNewProcess" name="My important process" >
        ...

The table will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>myProcess:1:676</p></td>
<td><p>myProcess</p></td>
<td><p>My important process</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>myProcess:2:870</p></td>
<td><p>myProcess</p></td>
<td><p>My important process</p></td>
<td><p>2</p></td>
</tr>
<tr class="odd">
<td><p>myNewProcess:1:1033</p></td>
<td><p>myNewProcess</p></td>
<td><p>My important process</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Note how the key for the new process is different from our first process. Even though the name is the same (we should probably have changed that too), Flowable only considers the id attribute when distinguishing processes. The new process is therefore deployed with version 1.

## Providing a process diagram

A process diagram image can be added to a deployment. This image will be stored in the Flowable repository and is accessible through the API. This image is also used to visualize the process in Flowable apps.

Suppose we have a process on our classpath, org/flowable/expenseProcess.bpmn20.xml that has a process key 'expense'. The following naming conventions for the process diagram image apply (in this specific order):

-   If an image resource exists in the deployment that has a name of the BPMN 2.0 XML file name concatenated with the process key and an image suffix, this image is used. In our example, this would be org/flowable/expenseProcess.expense.png (or .jpg/gif). In case you have multiple images defined in one BPMN 2.0 XML file, this approach makes most sense. Each diagram image will then have the process key in its file name.

-   If no such image exists, am image resource in the deployment matching the name of the BPMN 2.0 XML file is searched for. In our example this would be org/flowable/expenseProcess.png. Note that this means that **every process definition** defined in the same BPMN 2.0 file has the same process diagram image. In case there is only one process definition in each BPMN 2.0 XML file, this is obviously not a problem.

Example when deploying programmatically:

    repositoryService.createDeployment()
      .name("expense-process.bar")
      .addClasspathResource("org/flowable/expenseProcess.bpmn20.xml")
      .addClasspathResource("org/flowable/expenseProcess.png")
      .deploy();

The image resource can be retrieved through the API afterwards:

    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
      .processDefinitionKey("expense")
      .singleResult();

    String diagramResourceName = processDefinition.getDiagramResourceName();
    InputStream imageStream = repositoryService.getResourceAsStream(
        processDefinition.getDeploymentId(), diagramResourceName);

## Generating a process diagram

If no image is provided in the deployment, as described in the [previous section](bpmn/ch06-Deployment.md#providing-a-process-diagram), the Flowable engine will generate a process diagram image if the process definition contains the necessary 'diagram interchange' information.

The resource can be retrieved in exactly the same way as when [an image is provided](bpmn/ch06-Deployment.md#providing-a-process-diagram) in the deployment.



If, for some reason, it’s not necessary or desirable to generate a diagram during deployment, the isCreateDiagramOnDeploy property can be set on the process engine configuration:

    <property name="createDiagramOnDeploy" value="false" />

No diagram will be generated now.

## Category

Both deployments and process definitions have user-defined categories. The process definition category is initialized with the value of the targetNamespace attribute in the BPMN XML: &lt;definitions ... targetNamespace="yourCategory" ...

The deployment category can also be specified in the API like this:

    repositoryService
        .createDeployment()
        .category("yourCategory")
        ...
        .deploy();

---

### Docusaurus Docs Bpmn Ch07a BPMN Introduction (`docs/docusaurus/docs/bpmn/ch07a-BPMN-Introduction.md`)

---
id: ch07a-BPMN-Introduction
title: BPMN 2.0 Introduction
---

## What is BPMN?

BPMN is a widely accepted and supported standard notation for representing processes [OMG BPMN Standard](http://www.bpmn.org/).

## Defining a process

> **Note**
>
> This introduction is written with the assumption you are using the [Eclipse IDE](http://eclipse.org/) to create and edit files. Very little of this is specific to Eclipse, however, you can use any other tool you prefer to create XML files containing BPMN 2.0.

Create a new XML file (*right-click on any project and select New→Other→XML-XML File*) and give it a name. Make sure that the file **ends with .bpmn20.xml or .bpmn**, otherwise the engine won’t pick it up for deployment.



The root element of the BPMN 2.0 schema is the definitions element. Within this element, multiple process definitions can be given (although our advice is to have only one process definition in each file, as this simplifies maintenance later in the development process). An empty process definition looks like the one shown below. Note that the minimal definitions element only needs the xmlns and targetNamespace declaration. The targetNamespace can be anything and is useful for categorizing process definitions.

    <definitions
      xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
      xmlns:flowable="http://flowable.org/bpmn"
      targetNamespace="Examples">

      <process id="myProcess" name="My First Process">
        ..
      </process>

    </definitions>

Optionally, you can also add the online schema location of the BPMN 2.0 XML schema, as an alternative to the XML catalog configuration in Eclipse.

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL
                        http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd

The process element has two attributes:

-   **id**: this attribute is **required** and maps to the **key** property of a Flowable ProcessDefinition object. This id can then be used to start a new process instance of the process definition, through the startProcessInstanceByKey method on the RuntimeService. This method will always take the **latest deployed version** of the process definition.



    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");

-   Important to note here is that this is not the same as calling the startProcessInstanceById method, which expects the String ID that was generated at deploy time by the Flowable engine (the ID can be retrieved by calling the processDefinition.getId() method). The format of the generated ID is **'key:version'**, and the length is **constrained to 64 characters**. If you get a FlowableException stating that the generated ID is too long, limit the text in the *key* field of the process.

-   **name**: this attribute is **optional** and maps to the *name* property of a ProcessDefinition. The engine itself doesn’t use this property, so it can be used for displaying a more human-friendly name in a user interface, for example.

## Getting started: 10 minute tutorial

In this section we will cover a very simple business process that we will use to introduce some basic Flowable concepts and the Flowable API.

### Prerequisites

This tutorial assumes that you have the Flowable demo setup running, and that you are using a standalone H2 server. Edit db.properties and set the jdbc.url=jdbc:h2:tcp://localhost/flowable, and then run the standalone server according to [H2’s documentation](http://www.h2database.com/html/tutorial.html#using_server).

### Goal

The goal of this tutorial is to learn about Flowable and some basic BPMN 2.0 concepts. The end result will be a simple Java SE program that deploys a process definition, and then interacts with this process through the Flowable engine API. We’ll also touch on some of the tooling around Flowable. Of course, what you’ll learn in this tutorial can also be used when building your own web applications around your business processes.

### Use case

The use case is straightforward: we have a company, let’s call it BPMCorp. In BPMCorp, a financial report needs to be written every month for the company shareholders. This is the responsibility of the accountancy department. When the report is finished, one of the members of the upper management needs to approve the document before it’s sent to all the shareholders.

### Process diagram

The business process as described above can be defined graphically using the [Flowable Designer](bpmn/ch13-Designer.md#eclipse-designer). However, for this tutorial, we’ll type the XML ourselves, as we’ll learn the most this way at this stage. The graphical BPMN 2.0 notation of our process looks like this:



What we see is a [none Start Event](bpmn/ch07b-BPMN-Constructs.md#None-start-event) (circle on the left), followed by two [User Tasks](bpmn/ch07b-BPMN-Constructs.md#user-task): *'Write monthly financial report'* and *'Verify monthly financial report'*, ending in a [none end event](bpmn/ch07b-BPMN-Constructs.md#None-end-event) (circle with thick border on the right).

### XML representation

The XML version of this business process (*FinancialReportProcess.bpmn20.xml*) looks like that shown below. It’s easy to recognize the main elements of our process (click on the link to go to the detailed section of that BPMN 2.0 construct):

-   The [(none) start event](bpmn/ch07b-BPMN-Constructs.md#None-start-event) tells us what the *entry point* is to the process.

-   The [User Tasks](bpmn/ch07b-BPMN-Constructs.md#user-task) declarations are the representation of the human tasks of our process. Note that the first task is assigned to the *accountancy* group, while the second task is assigned to the *management* group. See [the section on user task assignment](bpmn/ch07b-BPMN-Constructs.md#user-assignment) for more information on how users and groups can be assigned to user tasks.

-   The process ends when the [none end event](bpmn/ch07b-BPMN-Constructs.md#None-end-event) is reached.

-   The elements are connected to each other by [sequence flows](bpmn/ch07b-BPMN-Constructs.md#sequence-flow). These sequence flows have a source and target, defining the *direction* of the sequence flow.



    <definitions id="definitions"
      targetNamespace="http://flowable.org/bpmn20"
      xmlns:flowable="http://flowable.org/bpmn"
      xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">

        <process id="financialReport" name="Monthly financial report reminder process">

          <startEvent id="theStart" />

          <sequenceFlow id="flow1" sourceRef="theStart" targetRef="writeReportTask" />

          <userTask id="writeReportTask" name="Write monthly financial report" >
            <documentation>
              Write monthly financial report for publication to shareholders.
            </documentation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>accountancy</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>

          <sequenceFlow id="flow2" sourceRef="writeReportTask" targetRef="verifyReportTask" />

          <userTask id="verifyReportTask" name="Verify monthly financial report" >
            <documentation>
              Verify monthly financial report composed by the accountancy department.
              This financial report is going to be sent to all the company shareholders.
            </documentation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>management</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>

          <sequenceFlow id="flow3" sourceRef="verifyReportTask" targetRef="theEnd" />

          <endEvent id="theEnd" />

        </process>

    </definitions>

### Starting a process instance

We have now created the **process definition** for our business process. From such a process definition, we can create **process instances**. In this scenario, one process instance corresponds to the creation and verification of a single financial report for a particular month. All the process instances for any month share the same process definition.

To be able to create process instances from a given process definition, we must first **deploy** the process definition. Deploying a process definition means two things:

-   The process definition will be stored in the persistent datastore that is configured for your Flowable engine. So by deploying our business process, we make sure that the engine will find the process definition after an engine restart.

-   The BPMN 2.0 process XML will be parsed to an in-memory object model that can be manipulated through the Flowable API.

More information on deployment can be found [in the dedicated section on deployment](bpmn/ch06-Deployment.md#deployment).

As described in that section, deployment can happen in several ways. One way is through the API as follows. Note that all interaction with the Flowable engine happens through its *services*.

    Deployment deployment = repositoryService.createDeployment()
      .addClasspathResource("FinancialReportProcess.bpmn20.xml")
      .deploy();

Now we can start a new process instance using the id we defined in the process definition (see process element in the XML). Note that this id in Flowable terminology is called the **key**.

    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");

This will create a process instance that will first go through the start event. After the start event, it follows all the outgoing sequence flows (only one in this case) and the first task ('write monthly financial report') is reached. The Flowable engine will now store a task in the persistent database. At this point, the user or group assignments attached to the task are resolved and also stored in the database. It’s important to note that the Flowable engine will continue process execution steps until it reaches a *wait state*, such as a user task. At such a wait state, the current state of the process instance is stored in the database. It remains in that state until a user decides to complete their task. At that point, the engine will continue until it reaches a new wait state or the end of the process. If the engine reboots or crashes in the meantime, the state of the process is safe and secure in the database.

After the task is created, the startProcessInstanceByKey method will return because the user task activity is a *wait state*. In our scenario, the task is assigned to a group, which means that every member of the group is a **candidate** to perform the task.

We can now throw this all together and create a simple Java program. Create a new Eclipse project and add the Flowable JARs and dependencies to its classpath (these can be found in the *libs* folder of the Flowable distribution). Before we can call the Flowable services, we must first construct a ProcessEngine that gives us access to the services. Here we use the *'standalone'* configuration, which constructs a ProcessEngine that uses the database also used in the demo setup.

You can download the process definition XML [here](assets/bpmn/FinancialReportProcess.bpmn20.xml). This file contains the XML shown above, but also contains the necessary BPMN [diagram interchange information](bpmn/ch06-Deployment.md#generating-a-process-diagram) to visualize the process in the Flowable tools.

    public static void main(String[] args) {

      // Create Flowable process engine
      ProcessEngine processEngine = ProcessEngineConfiguration
        .createStandaloneProcessEngineConfiguration()
        .buildProcessEngine();

      // Get Flowable services
      RepositoryService repositoryService = processEngine.getRepositoryService();
      RuntimeService runtimeService = processEngine.getRuntimeService();

      // Deploy the process definition
      repositoryService.createDeployment()
        .addClasspathResource("FinancialReportProcess.bpmn20.xml")
        .deploy();

      // Start a process instance
      runtimeService.startProcessInstanceByKey("financialReport");
    }

### Task lists

We can now retrieve this task through the TaskService by adding the following logic:

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

Note that the user we pass to this operation needs to be a member of the *accountancy* group, as that was declared in the process definition:

    <potentialOwner>
      <resourceAssignmentExpression>
        <formalExpression>accountancy</formalExpression>
      </resourceAssignmentExpression>
    </potentialOwner>

We could also use the task query API to get the same results using the name of the group. We can now add the following logic to our code:

    TaskService taskService = processEngine.getTaskService();
    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();

As we’ve configured our ProcessEngine to use the same database that the demo setup is using, we can now log into the [Flowable IDM](http://localhost:8080/flowable-idm/). Login as admin/test and create 2 new users *kermit* and *fozzie*, and give both of them the *Access the workflow application* privilege. Then create 2 new organization groups named *accountancy* and *management*, and add fozzie to the new accountancy group and add kermit to the management group.
Now login with fozzie to the [Flowable task](http://localhost:8080/flowable-task/) application, and we will find that we can start our business process by selecting the Task App, then its *Processes* page and selecting the *'Monthly financial report'* process.



As explained, the process will execute until reaching the first user task. As we’re logged in as fozzie, we can see that there is a new candidate task available for him after we’ve started a process instance. Select the *Tasks* page to view this new task. Note that even if the process was started by someone else, the task would still be visible as a candidate task to everyone in the accountancy group.



### Claiming the task

An accountant now needs to **claim the task**. By claiming the task, that specific user will become the **assignee** of the task, and the task will disappear from every task list of the other members of the accountancy group. Claiming a task is programmatically done as follows:

    taskService.claim(task.getId(), "fozzie");

The task is now in the **personal task list of the user that claimed the task**.

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

In the Flowable Task app, clicking the *claim* button will call the same operation. The task will now move to the personal task list of the logged on user. You’ll also see that the assignee of the task changed to the current logged in user.



### Completing the task

The accountant can now start working on the financial report. Once the report is finished, he can **complete the task**, which means that all work for that task is done.

    taskService.complete(task.getId());

For the Flowable engine, this is an external signal that the process instance execution can now continue. The task itself is removed from the runtime data. The single outgoing transition from the task is followed, moving the execution to the second task (*'verification of the report'*). The same mechanism as described for the first task will now be used to assign the second task, with the small difference that the task will be assigned to the *management* group.

In the demo setup, completing the task is done by clicking the *complete* button in the task list. Since Fozzie isn’t an accountant, we need to log out of the Flowable Task app and login in as *kermit* (who is a manager). The second task is now visible in the unassigned task lists.

### Ending the process

The verification task can be retrieved and claimed in exactly the same way as before. Completing this second task will move process execution to the end event, which finishes the process instance. The process instance and all related runtime execution data are removed from the datastore.

Programmatically, you can also verify that the process has ended, using the historyService

    HistoryService historyService = processEngine.getHistoryService();
    HistoricProcessInstance historicProcessInstance =
    historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
    System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());

### Code overview

Combine all the snippets from previous sections, and you should have something like the following. The code takes into account that you probably will have started a few process instances through the Flowable app UI. It retrieves a list of tasks instead of one task, so it always works:

    public class TenMinuteTutorial {

      public static void main(String[] args) {

        // Create Flowable process engine
        ProcessEngine processEngine = ProcessEngineConfiguration
          .createStandaloneProcessEngineConfiguration()
          .buildProcessEngine();

        // Get Flowable services
        RepositoryService repositoryService = processEngine.getRepositoryService();
        RuntimeService runtimeService = processEngine.getRuntimeService();

        // Deploy the process definition
        repositoryService.createDeployment()
          .addClasspathResource("FinancialReportProcess.bpmn20.xml")
          .deploy();

        // Start a process instance
        String procId = runtimeService.startProcessInstanceByKey("financialReport").getId();

        // Get the first task
        TaskService taskService = processEngine.getTaskService();
        List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
        for (Task task : tasks) {
          System.out.println("Following task is available for accountancy group: " + task.getName());

          // claim it
          taskService.claim(task.getId(), "fozzie");
        }

        // Verify Fozzie can now retrieve the task
        tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
        for (Task task : tasks) {
          System.out.println("Task for fozzie: " + task.getName());

          // Complete the task
          taskService.complete(task.getId());
        }

        System.out.println("Number of tasks for fozzie: "
                + taskService.createTaskQuery().taskAssignee("fozzie").count());

        // Retrieve and claim the second task
        tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
        for (Task task : tasks) {
          System.out.println("Following task is available for management group: " + task.getName());
          taskService.claim(task.getId(), "kermit");
        }

        // Completing the second task ends the process
        for (Task task : tasks) {
          taskService.complete(task.getId());
        }

        // verify that the process is actually finished
        HistoryService historyService = processEngine.getHistoryService();
        HistoricProcessInstance historicProcessInstance =
          historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
        System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
      }

    }

### Future enhancements

It’s easy to see that this business process is too simple to be usable in reality. However, as you are going through the BPMN 2.0 constructs available in Flowable, you will be able to enhance the business process by:

-   defining **gateways** so a manager can decide to reject the financial report and recreate the task for the accountant, following a different path than when accepting the report.

-   declaring and using **variables** to store or reference the report so that it can be visualized in the form.

-   defining a **service task** at the end of the process to send the report to every shareholder.

-   etc.

---

### Docusaurus Docs Bpmn Ch07b BPMN Constructs (`docs/docusaurus/docs/bpmn/ch07b-BPMN-Constructs.md`)

---
id: ch07b-BPMN-Constructs
title: BPMN 2.0 Constructs
---

This chapter covers the BPMN 20 constructs supported by Flowable, as well as custom extensions to the BPMN standard.

## Custom extensions

The BPMN 2.0 standard is a good thing for all parties involved. End-users don’t suffer from vendor lock-in that comes from depending on a proprietary solution. Frameworks, and particularly open-source frameworks such as Flowable, can implement a solution that has the same (and often better implemented ;-) features as those of a big vendor. Thanks to the BPMN 2.0 standard, the transition from such a big vendor solution towards Flowable can be an easy and smooth path.

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 very cumbersome. As Flowable puts ease of development as a top-priority, we introduced something called the **'Flowable BPMN extensions'**. These 'extensions' are new constructs or ways to simplify certain constructs that are not part of the BPMN 2.0 specification.

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

-   There **always** must be a simple transformation to the **standard way of doing things**, as a prerequisite of such a custom extension. So when you decide to use a custom extension, you don’t have to be concerned that there is no way back.

-   When using a custom extension, it is always clearly indicated by giving the new XML element, attribute, and so on, the **flowable:** namespace prefix. Note that the Flowable engine also supports the **activiti:** namespace prefix.

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, and so on). We only provide them as we believe that some points in the standard can be done in a simpler or more efficient way. Feel free to give us (positive 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!

## Events

Events are used to model something that happens during the lifetime of a process. Events are always visualized as a circle. In BPMN 2.0, there exist two main event categories: *catching* and *throwing* events.

-   **Catching:** when process execution arrives at the event, it will wait for a trigger to happen. The type of trigger is defined by the inner icon or the type declaration in the XML. Catching events are visually differentiated from a throwing event by the inner icon that is not filled (it’s just white).

-   **Throwing:** when process execution arrives at the event, a trigger is fired. The type of trigger is defined by the inner icon or the type declaration in the XML. Throwing events are visually differentiated from a catching event by the inner icon that is filled with black.

### Event Definitions

Event definitions define the semantics of an event. Without an event definition, an event "does nothing special". For instance, a start event without an event definition has nothing to specify what exactly starts the process. If we add an event definition to the start event (for example, a timer event definition), we declare what "type" of event starts the process (in the case of a timer event definition, the fact that a certain point in time is reached).

### Timer Event Definitions

Timer events are events that are triggered by a defined timer. They can be used as [start event](bpmn/ch07b-BPMN-Constructs.md#timer-start-event), [intermediate event](bpmn/ch07b-BPMN-Constructs.md#intermediate-catching-events) or [boundary event](bpmn/ch07b-BPMN-Constructs.md#timer-boundary-event). The behavior of the time event depends on the business calendar used. Every timer event has a default business calendar, but the business calendar can also be given as part of the timer event definition.

    <timerEventDefinition flowable:businessCalendarName="custom">
        ...
    </timerEventDefinition>

Where businessCalendarName points to a business calendar in the process engine configuration. When business calendar is omitted, default business calendars are used.

The timer definition must have exactly one element from the following:

-   **timeDate**. This format specifies a fixed date in [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601#Dates) format, when trigger will be fired. For example:



    <timerEventDefinition>
        <timeDate>2011-03-11T12:13:14</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](http://en.wikipedia.org/wiki/ISO_8601#Durations) format (as required by the BPMN 2.0 specification). For example (interval lasting 10 days):



    <timerEventDefinition>
        <timeDuration>P10D</timeDuration>
    </timerEventDefinition>

-   **timeCycle**. Specifies a repeating interval, which can be useful for starting process periodically, or for sending multiple reminders for overdue user task. A time cycle element can be in one of two formats. First, is the format of recurring time duration as specified by [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601#Repeating_intervals) standard. Example (3 repeating intervals, each lasting 10 hours):

It is also possible to specify the *endDate* as an optional attribute on the *timeCycle* or either in the end of the time expression as follows: R3/PT10H/${EndDate}.
When the endDate is reached, the application will stop creating other jobs for this task.
It accepts as a value either static values [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601#Dates) standard, for example, *"2015-02-25T16:42:11+00:00"*, or variables, for example, *${EndDate}*

    <timerEventDefinition>
        <timeCycle flowable:endDate="2015-02-25T16:42:11+00:00">R3/PT10H</timeCycle>
    </timerEventDefinition>

    <timerEventDefinition>
        <timeCycle>R3/PT10H/${EndDate}</timeCycle>
    </timerEventDefinition>

If both are specified, then the endDate specified as attribute will be used by the system.

Currently, only the *BoundaryTimerEvents* and *CatchTimerEvent* support *EndDate* functionality.

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

    0 0/5 * * * ?

Please see [this tutorial](http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html) for using cron expressions.

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

The recurring time duration is better suited for handling relative timers, which are calculated with respect to some particular point in time (for example, the time when a user task was started), while cron expressions can handle absolute timers, which is particularly useful for [timer start events](bpmn/ch07b-BPMN-Constructs.md#description).

You can use expressions for timer event definitions, and 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 appropriate timer type.
Additionally, for durations variables of type or expressions that return `java.time.Duration` can be used.

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

**Note:** timers are only fired when the async executor is enabled (*asyncExecutorActivate* must be set to true in the flowable.cfg.xml, because the async executor is disabled by default).

### Error Event Definitions

**Important note:** a BPMN error is NOT the same as a Java exception. In fact, the two have nothing in common. BPMN error events are a way of modeling *business exceptions*. Java exceptions are handled in [their own specific way](bpmn/ch07b-BPMN-Constructs.md#handling-exceptions).

    <endEvent id="myErrorEndEvent">
      <errorEventDefinition errorRef="myError" />
    </endEvent>

### Signal Event Definitions

Signal events are events that reference a named signal. A signal is an event of global scope (broadcast semantics) and is delivered to all active handlers (waiting process instances/catching signal events).

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 where a signal event is thrown and caught by intermediate events.

    <definitions... >
        
        <signal id="alertSignal" name="alert" />

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

The signalEventDefinitions reference the same signal element.

#### Throwing a Signal Event

A signal can either be thrown by a process instance using a BPMN construct or programmatically using the Java API. The following methods on the org.flowable.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 delivers the signal to a specific execution only.

#### Catching a Signal Event

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

#### Querying for Signal Event subscriptions

It’s possible to query for all executions that have subscribed to a specific signal event:

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

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

#### Signal event scope

By default, signals are *broadcast process engine wide*. This means that you can throw a signal event in a process instance, and other process instances with different process definitions can react on the occurrence of this event.

However, sometimes it is desirable to react to a signal event only within the *same process instance*. A use case, for example, is a synchronization mechanism in the process instance when two or more activities are mutually exclusive.

To restrict the *scope* of the signal event, add the (non-BPMN 2.0 standard!) *scope attribute* to the signal event definition:

    <signal id="alertSignal" name="alert" flowable:scope="processInstance"/>

The default value for this is attribute is *"global"*.

#### Signal Event example(s)

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 that are interested. The following is an example of a process subscribing to the event.



**Note:** it’s important to understand that a signal event is broadcast to **all** active handlers. This means, in the case of the example given above, that all instances of the process catching the signal will receive the event. In this scenario, this is what we want. However, there are also situations where the broadcast behavior is unintended. Consider the following process:



The pattern described in the process above is not supported by BPMN. The idea is that the error thrown while performing the "do something" task is caught by the boundary error event, propagated to the parallel path of execution using the signal throw event and then interrupt the "do something in parallel" task. So far, Flowable would perform as expected. The signal would be propagated to the catching boundary event and interrupt the task. **However, due to the broadcast semantics of the signal, it would also be propagated to all other process instances that have subscribed to the signal event.** In this case, this might not be what we want.

**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 deliver a signal to a specific process instance only, perform the correlation manually and use signalEventReceived(String signalName, String executionId) along with the appropriate [query mechanisms](bpmn/ch07b-BPMN-Constructs.md#querying-for-signal-event-subscriptions).

Flowable does have a way to fix this by adding the *scope* attribute to the signal event set to *processInstance*.

### Message Event Definitions

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

A message event definition is declared 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 where two message events is 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:flowable="http://flowable.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>

#### Throwing a Message Event

As an embeddable process engine, Flowable is not concerned with actually receiving a message. This would be environment dependent and entail 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 inside your application, you must decide what to do with it. If the message should trigger the start 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 start 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 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

-   In the 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();

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

-   In the 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")
          .variableValueEquals("orderId", message.getOrderId())
          .singleResult();

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

#### Message Event example(s)

The following is an example of a process that can be started using 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.

### Start Events

A start event indicates where a process starts. The type of start event (process starts on arrival of message, on specific time intervals, and so on), defining *how* the process is started, is shown as a small icon in the visual representation of the event. In the XML representation, the type is given by the declaration of a sub-element.

Start events **are always catching**: conceptually the event is (at any time) waiting until a certain trigger happens.

In a start event, the following Flowable-specific properties can be specified:

-   **initiator**: identifies the variable name in which the authenticated user ID will be stored when the process is started. For example:



    <startEvent id="request" flowable:initiator="initiator" />

The authenticated user must be set with the method IdentityService.setAuthenticatedUserId(String) in a try-finally block, like this:

    try {
      identityService.setAuthenticatedUserId("bono");
      runtimeService.startProcessInstanceByKey("someProcessKey");
    } finally {
      identityService.setAuthenticatedUserId(null);
    }

This code is baked into the Flowable application, so it works in combination with [???](bpmn/ch08-Forms.md#forms).

### None Start Event

#### Description

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 *startProcessInstanceByXXX* methods.

    ProcessInstance processInstance = runtimeService.startProcessInstanceByXXX();

*Note:* a sub-process always has a none start event.

#### Graphical notation

A none start event is visualized as a circle with no inner icon (in other words, no trigger type).



#### XML representation

The XML representation of a none start event is the normal start event declaration without any sub-element (other start event types all have a sub-element declaring the type).

    <startEvent id="start" name="my start event" />

#### Custom extensions for the none start event

**formKey**: references a form definition that users have to fill in when starting a new process instance. More information can be found in [the forms section](bpmn/ch08-Forms.md#forms) Example:

    <startEvent id="request" flowable:formKey="request" />

### Timer Start Event

#### Description

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

*Note:* a sub-process 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 startProcessInstanceByXXX, although calling start process methods is not restricted and will cause one more starting of the process at the time of startProcessInstanceByXXX invocation.

*Note:* when a new version of a process with a start timer event is deployed, the job corresponding with the previous timer will be removed. The reasoning is that normally it is not desirable to keep automatically starting new process instances of the old version of the process.

#### Graphical notation

A timer start event is visualized as a circle with clock inner icon.



#### XML representation

The XML representation of a timer start event is the normal start event declaration, with timer definition sub-element. Please refer to [timer definitions](bpmn/ch07b-BPMN-Constructs.md#timer-event-definitions) for configuration details.

Example: process will start 4 times, in 5 minute intervals, starting on 11th march 2011, 12:13

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

Example: process will start once, on selected date

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

### Message Start Event

#### Description

A [message](bpmn/ch07b-BPMN-Constructs.md#message-event-definitions) 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. A process definition must not have multiple message start events with the same name. Flowable throws an exception upon deployment of a process definition containing two or more message start events referencing 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. Flowable throws an exception upon deployment of a process definition containing one or more message start events referencing 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 start message subscriptions of the previous version are removed.

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 on top-level processes. Message start events are not supported on embedded sub processes.

-   If a process definition has multiple message start events, runtimeService.startProcessInstanceByMessage(...) allows to select the appropriate start event.

-   If a process definition has multiple message start events and a single none start event, runtimeService.startProcessInstanceByKey(...) and runtimeService.startProcessInstanceById(...) starts 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.

#### Graphical notation

A message start event is visualized as a circle with a message event symbol. The symbol is unfilled, to represent the catching (receiving) behavior.



#### XML representation

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:flowable="http://flowable.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>

### Signal Start Event

#### Description

A [signal](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions) start event can be used to start a process instance using a named signal. The signal can be 'fired' from within a process instance using the intermediary signal throw event or through the API (*runtimeService.signalEventReceivedXXX* methods). In both cases, all process definitions that have a signal start event with the same name will be started.

Note that in both cases, it is also possible to choose between a synchronous and asynchronous starting of the process instances.

The signalName that must be passed in the API is the name given in the name attribute of the signal element referenced by the signalRef attribute of the signalEventDefinition.

#### Graphical notation

A signal start event is visualized as a circle with a signal event symbol. The symbol is unfilled, to represent the catching (receiving) behavior.



#### XML representation

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

    <signal id="theSignal" name="The Signal" />

    <process id="processWithSignalStart1">
      <startEvent id="theStart">
        <signalEventDefinition id="theSignalEventDefinition" signalRef="theSignal"  />
      </startEvent>
      <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
      <userTask id="theTask" name="Task in process A" />
      <sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
      <endEvent id="theEnd" />
    </process>

### Error Start Event

#### Description

An [error](bpmn/ch07b-BPMN-Constructs.md#error-event-definitions) start event can be used to trigger an Event Sub-Process. **An error start event cannot be used for starting a process instance**.

An error start event is always interrupting.

#### Graphical notation

An error start event is visualized as a circle with an error event symbol. The symbol is unfilled, to represent the catching (receiving) behavior.



#### XML representation

The XML representation of an error start event is the normal start event declaration with an errorEventDefinition child-element:

    <startEvent id="messageStart" >
        <errorEventDefinition errorRef="someError" />
    </startEvent>

### End Events

An end event signifies the end of a path in a process or sub-process. An end event is **always throwing**. This means that when process execution arrives at an end event, a *result* is thrown. The type of result is depicted by the inner black icon of the event. In the XML representation, the type is given by the declaration of a sub-element.

### None End Event

#### Description

A 'none' end event means that the *result* thrown when the event is reached is unspecified. As such, the engine will not do anything extra besides ending the current path of execution.

#### Graphical notation

A none end event is visualized as a circle with a thick border with no inner icon (no result type).



#### XML representation

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

### Error End Event

#### Description

When process execution arrives at an **error end event**, the current path of execution ends and an error is thrown. This error can [caught by a matching intermediate boundary error event](bpmn/ch07b-BPMN-Constructs.md#error-boundary-event). If no matching boundary error event is found, an exception will be thrown.

#### Graphical notation

An error end event is visualized as a typical end event (circle with thick border), with the error icon inside. The error icon is completely black, to indicate its throwing semantics.



#### XML representation

An error end event is represented as an end event, with an *errorEventDefinition* child element.

    <endEvent id="myErrorEndEvent">
      <errorEventDefinition errorRef="myError" />
    </endEvent>

The *errorRef* attribute can reference an *error* element that is defined outside the process:

    <error id="myError" errorCode="123" />
    ...
    <process id="myProcess">
    ...

The **errorCode** of the *error* will be used to find the matching catching boundary error event. If the *errorRef* doesn’t match any defined *error*, then the *errorRef* is used as a shortcut for the *errorCode*. This is a Flowable specific shortcut. More concretely, the following snippets are equivalent in functionality.

    <error id="myError" errorCode="error123" />
    ...
    <process id="myProcess">
    ...
      <endEvent id="myErrorEndEvent">
        <errorEventDefinition errorRef="myError" />
      </endEvent>
    ...

is equivalent with

    <endEvent id="myErrorEndEvent">
      <errorEventDefinition errorRef="error123" />
    </endEvent>

Note that the *errorRef* must comply with the BPMN 2.0 schema, and must be a valid QName.

### Terminate End Event

#### Description

When a *terminate end event* is reached, the current process instance or sub-process will be terminated. Conceptually, when an execution arrives at a terminate end event, the first *scope* (process or sub-process) will be determined and ended. Note that in BPMN 2.0, a sub-process can be an embedded sub-process, call activity, event sub-process or transaction sub-process. This rule applies in general: when, for example, there is a multi-instance call activity or embedded sub-process, only that instance will end, the other instances and the process instance are not affected.

There is an optional attribute *terminateAll* that can be added. When *true*, regardless of the placement of the terminate end event in the process definition and regardless of being in a sub-process (even nested), the (root) process instance will be terminated.

#### Graphical notation

A cancel end event visualized as a typical end event (circle with thick outline), with a full black circle inside.



#### XML representation

A terminate end event is represented as an end event, with a *terminateEventDefinition* child element.

Note that the *terminateAll* attribute is optional (and *false* by default).

    <endEvent id="myEndEvent >
      <terminateEventDefinition flowable:terminateAll="true"></terminateEventDefinition>
    </endEvent>

### Cancel End Event

#### Description

The cancel end event can only be used in combination with a BPMN transaction sub-process. 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.

#### Graphical notation

A cancel end event is visualized as a typical end event (circle with thick outline), with the cancel icon inside. The cancel icon is completely black, to indicate its throwing semantics.



#### XML representation

A cancel end event is represented as an end event, with a *cancelEventDefinition* child element.

    <endEvent id="myCancelEndEvent">
      <cancelEventDefinition />
    </endEvent>

### Boundary Events

Boundary events are *catching* events that are attached to an activity (a boundary event can never be throwing). This means that while the activity is running, the event is *listening* for a certain type of trigger. When the event is *caught*, the activity is interrupted and the sequence flow going out of the event is followed.

All boundary events are defined in the same way:

    <boundaryEvent id="myBoundaryEvent" attachedToRef="theActivity">
          <XXXEventDefinition/>
    </boundaryEvent>

A boundary event is defined with

-   A unique identifier (process-wide)

-   A reference to the activity to which the event is attached through the **attachedToRef** attribute.
    Note that a boundary event is defined on the same level as the activities to which they are attached (in other words, no inclusion of the boundary event inside the activity).

-   An XML sub-element of the form *XXXEventDefinition* (for example, *TimerEventDefinition*, *ErrorEventDefinition*, and so on) defining the type of the boundary event. See the specific boundary event types for more details.

### Timer Boundary Event

#### Description

A timer boundary event acts as a stopwatch and alarm clock. When an execution arrives at the activity where the boundary event is attached, a timer is started. When the timer fires (for example, after a specified interval), the activity is interrupted and the sequence flow going out of the boundary event is followed.

#### Graphical Notation

A timer boundary event is visualized as a typical boundary event (circle on the border), with the timer icon on the inside.



#### XML Representation

A timer boundary event is defined as a [regular boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events). The specific type sub-element in this case is a **timerEventDefinition** element.

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

Please refer to [timer event definition](bpmn/ch07b-BPMN-Constructs.md#timer-event-definitions) for details on timer configuration.

In the graphical representation, the line of the circle is dotted as you can see in the example above:



A typical use case is sending an escalation email after a period of time, but without affecting the normal process flow.

There is a key difference between the interrupting and non interrupting timer event. Non-interrupting means the original activity is **not** interrupted but stays as it was. The interrupting behavior is the default. In the XML representation, the *cancelActivity* attribute is set to false:

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

**Note:** boundary timer events are only fired when the async executor is enabled (*asyncExecutorActivate* needs to be set to true in the flowable.cfg.xml, since the async executor is disabled by default).

#### 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 flows attached to a boundary event. A solution to this problem is to use one outgoing sequence flow that goes to a parallel gateway.



### Error Boundary Event

#### Description

An intermediate *catching* error 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 sub-process](bpmn/ch07b-BPMN-Constructs.md#aocess), or a [call activity](bpmn/ch07b-BPMN-Constructs.md#call-activity-(sub-process)), as a sub-process creates a scope for all activities inside the sub-process. Errors are thrown by [error end events](bpmn/ch07b-BPMN-Constructs.md#error-end-event). 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 within (concurrent activities, nested sub-processes, and so on). Process execution continues following the outgoing sequence flow of the boundary event.

#### Graphical notation

A boundary error event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the error icon inside. The error icon is white, to indicate its *catch* semantics.



#### XML representation

A boundary error event is defined as a typical [boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events):

    <boundaryEvent id="catchError" attachedToRef="mySubProcess">
      <errorEventDefinition errorRef="myError"/>
    </boundaryEvent>

As with the [error end event](bpmn/ch07b-BPMN-Constructs.md#error-end-event), the *errorRef* references an error defined outside the process element:

    <error id="myError" errorCode="123" />
    ...
    <process id="myProcess">
    ...

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

-   If an *errorRef* is provided and it references an existing *error*, the boundary event will **only catch errors with the same error code**.

-   If an *errorRef* is provided, but no *error* is defined in the BPMN 2.0 file, then the **errorRef is used as errorCode** (similar for with error end events).

#### Example

The following example process shows how an error end event can be used. When the *'Review profitability'* user task is completed by saying that not enough information is provided, an error is thrown. When this error is caught on the boundary of the sub-process, all active activities within the *'Review sales lead'* sub-process are destroyed (even if *'Review customer rating'* had not yet been completed), and the *'Provide additional details'* user task is created.



This process is shipped as example in the demo setup. The process XML and unit test can be found in the *org.flowable.examples.bpmn.event.error* package.

### Signal Boundary Event

#### Description

An attached intermediate *catching* [signal](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions) on the boundary of an activity, or **boundary signal event** for short, catches signals with the same signal name as the referenced signal definition.

**Note:** contrary to other events, such as the boundary error event, a boundary signal event doesn’t only catch signal events thrown from the scope to which it is attached. On the contrary, a signal event has global scope (broadcast semantics), meaning that the signal can be thrown from any place, even from a different process instance.

**Note:** contrary to other events, such as the error event, 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, even if they are part of different process instances.

#### Graphical notation

A boundary signal event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the signal icon inside. The signal icon is white (unfilled), to indicate its *catch* semantics.



#### XML representation

A boundary signal event is defined as a typical [boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events):

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

#### Example

See the section on [signal event definitions](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions).

### Message Boundary Event

#### Description

An attached intermediate *catching* [message](bpmn/ch07b-BPMN-Constructs.md#message-event-definitions) on the boundary of an activity, or **boundary message event** for short, catches messages with the same message name as the referenced message definition.

#### Graphical notation

A boundary message event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the message icon inside. The message icon is white (unfilled), to indicate its *catch* semantics.



Note that boundary message event can be both interrupting (right-hand side) and non-interrupting (left-hand side).

#### XML representation

A boundary message event is defined as a typical [boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events):

    <boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
        <messageEventDefinition messageRef="newCustomerMessage"/>
    </boundaryEvent>

#### Example

See the section on [message event definitions](bpmn/ch07b-BPMN-Constructs.md#message-event-definitions).

### Cancel Boundary Event

#### Description

An attached intermediate *catching* cancel event on the boundary of a transaction sub-process, or **boundary cancel event** for short, is triggered when a transaction is canceled. When the cancel boundary event is triggered, it first interrupts all active executions in the current scope. Next, it starts compensation for all active compensation boundary events in the scope of the transaction. Compensation is performed synchronously, in other words, the boundary event waits before compensation is completed before leaving the transaction. When compensation is completed, the transaction sub-process is left using any sequence flows running out of the cancel boundary event.

**Note:** Only a single cancel boundary event is allowed for a transaction sub-process.

**Note:** If the transaction sub-process hosts nested sub-processes, compensation is only triggered for sub-processes that have completed successfully.

**Note:** If a cancel boundary event is placed on a transaction sub-process with multi instance characteristics, if one instance triggers cancellation, the boundary event cancels all instances.

#### Graphical notation

A cancel boundary event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the cancel icon inside. The cancel icon is white (unfilled), to indicate its *catching* semantics.



#### XML representation

A cancel boundary event is defined as a typical [boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events):

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

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

### Compensation Boundary Event

#### Description

An attached intermediate *catching* compensation on the boundary of an activity or **compensation boundary event** for short, 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 from 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 finished, they are deactivated and the corresponding event subscription is canceled. The compensation boundary event is different. The compensation boundary event is activated when the activity it is attached to **completes successfully**. At this point, the corresponding subscription to the compensation events is created. The subscription is removed either when a compensation event is triggered or when the corresponding process instance ends. From this, it follows:

-   When compensation is triggered, the compensation handler associated with the compensation boundary event is invoked the same number of times 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 that is contained inside a loop, a compensation event subscription is created 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 sub-processes.

#### Graphical notation

A compensation boundary event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the compensation icon inside. The compensation icon is white (unfilled), to indicate its *catching* semantics. In addition to a compensation boundary event, the following figure shows a compensation handler associated with the boundary event using a unidirectional association:



#### XML representation

A compensation boundary event is defined as a typical [boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events):

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

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

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

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

### Intermediate Catching Events

All intermediate catching events are defined in the same way:

    <intermediateCatchEvent id="myIntermediateCatchEvent" >
        <XXXEventDefinition/>
    </intermediateCatchEvent>

An intermediate catching event is defined with:

-   A unique identifier (process-wide)

-   An XML sub-element of the form *XXXEventDefinition* (for example, *TimerEventDefinition*) defining the type of the intermediate catching event. See the specific catching event types for more details.

### Timer Intermediate Catching Event

#### Description

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

#### Graphical Notation

A timer intermediate event is visualized as an intermediate catching event, with the timer icon on the inside.



#### XML Representation

A timer intermediate event is defined as an [intermediate catching event](bpmn/ch07b-BPMN-Constructs.md#intermediate-catching-events). The specific type sub-element is, in this case, a **timerEventDefinition** element.

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

See [timer event definitions](bpmn/ch07b-BPMN-Constructs.md#timer-event-definitions) for configuration details.

### Signal Intermediate Catching Event

#### Description

An intermediate *catching* [signal](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions) event catches signals with the same signal name as the referenced signal definition.

**Note:** contrary to other events, such as an error event, 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, even if they are part of different process instances.

#### Graphical notation

An intermediate signal catch event is visualized as a typical intermediate event (circle with smaller circle inside), with the signal icon inside. The signal icon is white (unfilled), to indicate its *catch* semantics.



#### XML representation

A signal intermediate event is defined as an [intermediate catching event](bpmn/ch07b-BPMN-Constructs.md#intermediate-catching-events). The specific type sub-element is in this case a **signalEventDefinition** element.

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

#### Example

See the section on [signal event definitions](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions).

### Message Intermediate Catching Event

#### Description

An intermediate *catching* [message](bpmn/ch07b-BPMN-Constructs.md#message-event-definitions) event catches messages with a specified name.

#### Graphical notation

An intermediate catching message event is visualized as a typical intermediate event (circle with smaller circle inside), with the message icon inside. The message icon is white (unfilled), to indicate its *catch* semantics.



#### XML representation

A message intermediate event is defined as an [intermediate catching event](bpmn/ch07b-BPMN-Constructs.md#intermediate-catching-events). The specific type sub-element is in this case a **messageEventDefinition** element.

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

#### Example

See the section on [message event definitions](bpmn/ch07b-BPMN-Constructs.md#message-event-definitions).

### Intermediate Throwing Event

All intermediate throwing events are defined in the same way:

    <intermediateThrowEvent id="myIntermediateThrowEvent" >
          <XXXEventDefinition/>
    </intermediateThrowEvent>

An intermediate throwing event is defined with:

-   A unique identifier (process-wide)

-   An XML sub-element of the form *XXXEventDefinition* (for example, *signalEventDefinition*) defining the type of the intermediate throwing event. See the specific throwing event types for more details.

### Intermediate Throwing None Event

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 KPIs, by adding an [execution listener](bpmn/ch07b-BPMN-Constructs.md#execution-listener).

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

Here you can add some of your own code to maybe send some event to your BAM tool or DWH. The engine itself doesn’t do anything in that case, it just passes through.

### Signal Intermediate Throwing Event

#### Description

An intermediate *throwing* [signal](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions) event throws a signal event for a defined signal.

In Flowable, the signal is broadcast to all active handlers (in other words, 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 this 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.

#### Graphical notation

An intermediate signal throw event is visualized as a typical intermediate event (circle with smaller circle inside), with the signal icon inside. The signal icon is black (filled), to indicate its *throw* semantics.



#### XML representation

A signal intermediate event is defined as an [intermediate throwing event](bpmn/ch07b-BPMN-Constructs.md#intermediate-throwing-event). The specific type sub-element is in this case a **signalEventDefinition** element.

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

An asynchronous signal event would look like this:

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

#### Example

See the section on [signal event definitions](bpmn/ch07b-BPMN-Constructs.md#signal-event-definitions).

### Compensation Intermediate Throwing Event

#### Description

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 number of times the activity completed successfully.

-   If compensation is thrown for the current scope, all activities within the current scope are compensated, which includes activities on concurrent branches.

-   Compensation is triggered hierarchically: if the activity to be compensated is a sub-process, compensation is triggered for all activities contained in the sub-process. If the sub-process 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 sub-process, it is not propagated to activities outside of the sub-process scope. The BPMN specification states that compensation is triggered for activities at "the same level of sub-process".

-   In Flowable, compensation is performed in reverse order of execution. This means that whichever activity completed last is compensated first, and so on.

-   The intermediate throwing compensation event can be used to compensate transaction sub-processes that competed successfully.

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



In this process we have two concurrent executions: one executing the embedded sub-process and one executing the "charge credit card" activity. Let’s 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 sub-process is not yet completed which means that the compensation event is not propagated to the sub-process and consequently the "cancel hotel reservation" compensation handler is not executed. If the user task (and therefore the embedded sub-process) completes before the "cancel reservations" is performed, compensation is propagated to the embedded sub-process.

**Process variables:** When compensating an embedded sub-process, the execution used for executing the compensation handlers has access to the local process variables of the sub-process in the state they were in when the sub-process completed execution. To achieve this, a snapshot of the process variables associated with the scope execution (execution created for executing the sub-process) 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 sub-process scope.

-   Process variables associated with executions higher up in the hierarchy (for instance, 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 sub-processes, 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.

-   Compensation is not propagated to sub-process instances spawned by call activities.

#### Graphical notation

An intermediate compensation throw event is visualized as a typical intermediate event (circle with smaller circle inside), with the compensation icon inside. The compensation icon is black (filled), to indicate its *throw* semantics.



#### XML representation

A compensation intermediate event is defined as an [intermediate throwing event](bpmn/ch07b-BPMN-Constructs.md#intermediate-throwing-event). The specific type sub-element is in this case a **compensateEventDefinition** element.

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

In addition, the optional argument activityRef can be used to trigger compensation of a specific scope or activity:

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

## Sequence Flow

### Description

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.

### Graphical notation

A sequence flow is visualized as an arrow going from the source element towards the target element. The arrow always points towards the target.



### XML representation

Sequence flows need to have a process-unique **id** and references to an existing **source** and **target** element.

    <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />

### Conditional sequence flow

#### Description

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 flows. When a condition evaluates to *true*, that outgoing sequence flow is selected. When multiple sequence flows are selected that way, multiple *executions* will be generated and the process will be continued in a parallel way.

**Note:** the above holds for BPMN 2.0 activities (and events), but not for gateways. Gateways will handle sequence flows with conditions in specific ways, depending on the gateway type.

#### Graphical notation

A conditional sequence flow is visualized as a regular sequence flow, with a small diamond at the beginning. The condition expression is shown next to the sequence flow.



#### XML representation

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

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

Currently, conditionalExpressions can **only be used with UEL**. Detailed information about these can be found in the section on [Expressions](bpmn/ch04-API.md#expressions). The expression used should resolve to a boolean value, otherwise an exception is thrown while evaluating the condition.

-   The example below references the 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>

The Flowable distribution contains the following example process using value and method expressions (see *org.flowable.examples.bpmn.expression)*:



### Default sequence flow

#### Description

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.

#### Graphical notation

A default sequence flow is visualized as a regular sequence flow, with a 'slash' marker at the beginning.



#### XML representation

A default sequence flow for a certain activity is defined by the **default attribute** on that activity. The following XML snippet shows an example of an exclusive gateway that has as default sequence flow, *flow 2*. Only when *conditionA* and *conditionB* both evaluate to false, will it be chosen as the outgoing sequence flow for the gateway.

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

    <sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1">
        <conditionExpression xsi:type="tFormalExpression">${conditionA}</conditionExpression>
    </sequenceFlow>

    <sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/>

    <sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3">
        <conditionExpression xsi:type="tFormalExpression">${conditionB}</conditionExpression>
    </sequenceFlow>

Which corresponds with the following graphical representation:

## Gateways

A gateway is used to control the flow of execution (or as the BPMN 2.0 describes, the *tokens* of execution). A gateway is capable of *consuming* or *generating* tokens.

A gateway is graphically visualized as a diamond shape, with an icon inside. The icon shows the type of gateway.



### Exclusive Gateway

#### Description

An exclusive gateway (also called the *XOR gateway* or more technical 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 are defined. The first sequence flow whose condition evaluates to true (or doesn’t have a condition set, conceptually having a *'true'* defined on the sequence flow) is selected for continuing the process.

**Note that the semantics of the outgoing sequence flow is different in this case to that of the general case in BPMN 2.0. While, in general, all sequence flows whose condition evaluates to true are selected to continue in a parallel way, only one sequence flow is selected when using the exclusive gateway. If multiple sequence flows 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, an exception will be thrown.**

#### Graphical notation

An exclusive gateway is visualized as a typical gateway (a diamond shape) with an 'X' icon inside, referring to the *XOR* semantics. Note that a gateway without an icon inside defaults to an exclusive gateway. The BPMN 2.0 specification does not permit use of both the diamond with and without an X in the same process definition.



#### XML representation

The XML representation of an exclusive gateway is straight-forward: one line defining the gateway and condition expressions defined on the outgoing sequence flows. See the section on [conditional sequence flow](bpmn/ch07b-BPMN-Constructs.md#conditional-sequence-flow) to see which options are available for such expressions.

Take, for example, the following model:



Which is represented in XML as follows:

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

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

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

    <sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3">
      <conditionExpression xsi:type="tFormalExpression">${input == 3}</conditionExpression>
    </sequenceFlow>

### Parallel Gateway

#### Description

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 you to *fork* into multiple paths of execution or *join* multiple incoming paths of execution.

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

-   **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 in 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 behavior**, if there are multiple incoming and outgoing sequence flows for the same parallel gateway. In this 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 flows connected with the parallel gateway, they are simply ignored.**

#### Graphical Notation

A parallel gateway is visualized as a gateway (diamond shape) with the 'plus' symbol inside, referring to the 'AND' semantics.



#### XML representation

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 example above, 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 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 a parallel gateway does not need to be 'balanced' (a matching number of incoming/outgoing sequence flow 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:



### Inclusive Gateway

#### Description

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. But the main difference is that the inclusive gateway can take more than one sequence flow, like the parallel gateway.

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

-   **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 with 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 this 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.

#### Graphical Notation

An inclusive gateway is visualized as a gateway (diamond shape) with the 'circle' symbol inside.



#### XML representation

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 example above, after the process is started, two tasks will be created if the process variables paymentReceived == false and shipOrder == true. If only one of these process variables equals 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 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 an inclusive gateway does not need to be 'balanced' (a matching number of incoming/outgoing sequence flow for corresponding inclusive gateways). An inclusive gateway will simply wait for all incoming sequence flow and create a concurrent path of execution for each outgoing sequence flow, not influenced by other constructs in the process model.

### Event-based Gateway

#### Description

The Event-based Gateway provides a way to take 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 from 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 must only be connected to elements of type intermediateCatchEvent (Receive Tasks after an Event-based Gateway are not supported by Flowable).

-   An intermediateCatchEvent connected to an Event-based Gateway must have a single incoming sequence flow.

#### Graphical notation

An Event-based Gateway is visualized as a diamond shape like other BPMN gateways with a special icon inside.



#### XML representation

The XML element used to define an Event-based Gateway is eventBasedGateway.

#### Example(s)

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. In addition, the process instance subscribes to the alert signal event and creates a timer that fires after 10 minutes. This effectively causes the process engine to wait for ten minutes for a signal event. If the signal occurs within 10 minutes, the timer is cancelled and execution continues after the signal. If the signal is not fired, execution continues after the timer and the signal subscription is canceled.



    <definitions id="definitions"
        xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:flowable="http://flowable.org/bpmn"
        targetNamespace="Examples">

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

## Tasks

### User Task

#### Description

A 'user task' is used to model work that needs to be done by a human. When the process execution arrives at such a user task, a new task is created in the task list of any users or groups assigned to that task.

#### Graphical notation

A user task is visualized as a typical task (rounded rectangle), with a small user icon in the left upper corner.



#### XML representation

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

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

A user task can also have 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 given date.

There is an activity extension that 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), ISO8601 time-duration (for example, PT50M) or null**. For example, you could use a date that was entered in a previous form in the process or calculated in a previous Service Task. If a time-duration is used, the due-date is calculated based on the current time and incremented by the given period. For example, when "PT30M" is used as dueDate, the task is due in thirty minutes from now.

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

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

#### 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 as the human performer for the task. In Flowable terminology, this user is called the **assignee**. Tasks that have an assignee are not visible in the task lists of other people and can be found in the **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 **candidate task list** of people. In this case, the **potentialOwner** construct must be used. The usage is similar to the *humanPerformer* construct. Do note that it is necessary to specify if it is a user or a group defined for each element in the formal expression (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* usage as for the tasks with an assignee):

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

This will retrieve all tasks where kermit is a **candidate user**, in other words, the formal expression contains *user(kermit)*. This will also retrieve all tasks that are **assigned to a group of which kermit is a member** (for example, *group(management)*, if kermit is a member of that group and the Flowable identity component is used). The user’s groups are resolved at runtime and these can be managed through the [IdentityService](bpmn/ch04-API.md#the-process-engine-api-and-services).

If no specifics are given as to whether the given text string is a user or group, the engine defaults to group. The following would be the same as when *group(accountancy) was declared*.

    <formalExpression>accountancy</formalExpression>

#### Flowable extensions for task assignment

It is clear that user and group assignments are quite cumbersome for use cases where the assignment is not complex. To avoid these complexities, [custom extensions](bpmn/ch07b-BPMN-Constructs.md#custom-extensions) on the user task are possible.

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



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

This is exactly the same as using a **humanPerformer** construct as defined [above](bpmn/ch07b-BPMN-Constructs.md#user-assignment).

-   **candidateUsers attribute**: this custom extension makes a given user a candidate for a task.



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

This is exactly the same as using the **potentialOwner** construct as defined [above](bpmn/ch07b-BPMN-Constructs.md#user-assignment). Note that it is not necessary to use the *user(kermit)* declaration, as with the case of the *potential owner* construct, since the attribute can only be used for users.

-   **candidateGroups attribute**: this custom extension makes a given group a candidate for a task.



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

This is exactly the same as using a **potentialOwner** construct as defined [above](bpmn/ch07b-BPMN-Constructs.md#user-assignment). Note that it is not necessary to use the *group(management)* declaration, as with the case of the *potential owner* construct, since the attribute can only be used for groups.

-   *candidateUsers* and *candidateGroups* can both be defined on the same user task.

Note: Although Flowable provides an identity management component, which is exposed through the [IdentityService](bpmn/ch04-API.md#the-process-engine-api-and-services), no check is made whether a provided user is known by the identity component. This is to allow Flowable to integrate with existing identity management solutions when it is embedded in an application.

#### Custom identity link types

The BPMN standard supports a single assigned user or **humanPerformer** or a set of users that form a potential pool of **potentialOwners**, as defined in [User assignment](bpmn/ch07b-BPMN-Constructs.md#user-assignment). In addition, Flowable defines [extension attribute elements](bpmn/ch07b-BPMN-Constructs.md#flowable-extensions-for-task-assignment) for the User Task that can represent the task **assignee** or **candidate owner**.

The supported Flowable identity link types are:

    public class IdentityLinkType {
      /* Flowable native roles */
      public static final String ASSIGNEE = "assignee";
      public static final String CANDIDATE = "candidate";
      public static final String OWNER = "owner";
      public static final String STARTER = "starter";
      public static final String PARTICIPANT = "participant";
    }

The BPMN standard and Flowable example authorization identities are **user** and **group**. As mentioned in the previous section, the Flowable identity management implementation is not intended for production use, but should be extended depending on the supported authorization scheme.

If additional link types are required, custom resources can be defined as extension elements with the following syntax:

    <userTask id="theTask" name="make profit">
      <extensionElements>
        <flowable:customResource flowable:name="businessAdministrator">
          <resourceAssignmentExpression>
            <formalExpression>user(kermit), group(management)</formalExpression>
          </resourceAssignmentExpression>
        </flowable:customResource>
      </extensionElements>
    </userTask>

The custom link expressions are added to the *TaskDefinition* class:

    protected Map<String, Set<Expression>> customUserIdentityLinkExpressions =
        new HashMap<String, Set<Expression>>();
    protected Map<String, Set<Expression>> customGroupIdentityLinkExpressions =
        new HashMap<String, Set<Expression>>();

    public Map<String, Set<Expression>> getCustomUserIdentityLinkExpressions() {
        return customUserIdentityLinkExpressions;
    }

    public void addCustomUserIdentityLinkExpression(
            String identityLinkType, Set<Expression> idList) {

        customUserIdentityLinkExpressions.put(identityLinkType, idList);
    }

    public Map<String, Set<Expression>> getCustomGroupIdentityLinkExpressions() {
        return customGroupIdentityLinkExpressions;
    }

    public void addCustomGroupIdentityLinkExpression(
            String identityLinkType, Set<Expression> idList) {

        customGroupIdentityLinkExpressions.put(identityLinkType, idList);
    }

These are populated at runtime by the *UserTaskActivityBehavior handleAssignments* method.

Finally, the *IdentityLinkType* class must be extended to support the custom identity link types:

    package com.yourco.engine.task;

    public class IdentityLinkType extends org.flowable.engine.task.IdentityLinkType {

        public static final String ADMINISTRATOR = "administrator";

        public static final String EXCLUDED_OWNER = "excludedOwner";
    }

#### Custom Assignment via task listeners

If the previous approaches are not sufficient, it is possible to delegate to custom assignment logic using a [task listener](bpmn/ch07b-BPMN-Constructs.md#task-listener) on the create event:

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

The DelegateTask that is passed to the TaskListener implementation can 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, it is possible to use the custom assignment attributes as described in the section above, and delegate to a Spring bean using a [task listener](bpmn/ch07b-BPMN-Constructs.md#task-listener) with an [expression](bpmn/ch05-Spring.md#expressions) that listens to task *create* events. In the following example, the assignee will be set by calling the findManagerOfEmployee on the ldapService Spring bean. The *emp* parameter that is passed, is a process variable&gt;.

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

This also works similarly for candidate users and groups:

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

Note that this will only work if the return type of the invoked method is String or Collection&lt;String&gt; (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");
      }

    }

### Script Task

#### Description

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

Properties:

-   **name**: task attribute to indicate the name of the task

-   **type**: task attribute whose value must be "script" to indicate the type of task

-   **scriptFormat**: extended attribute that indicate the language of the script (for example, javascript, groovy)

-   **script**: the script to execute, defined as a string in a field element named "script"

-   **autoStoreVariables**: optional task attribute flag (default: false) that indicates whether or not variables defined in the script will be stored in the Execution context (see note below)

-   **resultVariableName**: optional task attribute that when present will store a variable with the specified name in the Execution context with the script evaluation result (see note below)

#### Graphical Notation

A script task is visualized as a typical BPMN 2.0 task (rounded rectangle), with a small 'script' icon in the top-left corner of the rectangle.



#### XML representation

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 the [JSR-223](http://jcp.org/en/jsr/detail?id=223) (scripting for the Java platform). By default, JavaScript is included in every JDK and as such doesn’t need any additional JAR files. If you want to use another (JSR-223 compatible) scripting engine, it is sufficient to add the corresponding JAR to the classpath and use the appropriate name. For example, the Flowable unit tests often use Groovy because the syntax is similar to that of Java.

Do note that the Groovy scripting engine is bundled with the groovy-jsr223 jar. As such, one must add the following dependency:

    <dependency>
        <groupId>org.apache.groovy</groupId>
        <artifactId>groovy-jsr223</artifactId>
        <version>4.x.x<version>
    </dependency>

#### 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, 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, simply by calling *execution.setVariable("variableName", variableValue)*. By default, no variables are stored automatically (**Note: in some older releases this was the case!**). It’s possible to automatically store any variable defined in the script (for example, *sum* in the example above) by setting the property autoStoreVariables on the scriptTask to true. However, **the best practice is not to do this and use an explicit execution.setVariable() call**, as with some recent versions of the JDK, auto storing of variables does not work for some scripting languages. See [this link](http://www.jorambarrez.be/blog/2013/03/25/bug-on-jdk-1-7-0_17-when-using-scripttask-in-activiti/) for more details.

    <scriptTask id="script" scriptFormat="JavaScript" flowable:autoStoreVariables="false">

The default for this parameter is false, meaning that if the parameter is omitted from the script task definition, all the declared variables will only exist during the duration of the script.

Here’s an example of how to set a variable in a script:

    <script>
        def scriptVar = "test123"
        execution.setVariable("myVar", scriptVar)
    </script>

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 an already existing, or to a new process variable, by specifying the process variable name as a literal value for the *'flowable: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" flowable: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.

#### Security

It is also possible when using *javascript* as the scripting language to use '*secure scripting*'. See the [secure scripting section](bpmn/ch18-Advanced.md#secure-scripting).

### Java Service Task

#### Description

A Java service task is used to invoke an external Java class.

#### Graphical Notation

A service task is visualized as a rounded rectangle with a small gear icon in the top-left corner.



#### XML representation

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

-   Specifying a class that implements JavaDelegate, FutureJavaDelegate 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 **'flowable:class'** attribute.

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

See [the implementation section](bpmn/ch07b-BPMN-Constructs.md#implementation) for more details on how to use such a class.

It’s 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 flowable:class attribute is used (see [further](bpmn/ch07b-BPMN-Constructs.md#implementation)).

    <serviceTask id="serviceTask" flowable:delegateExpression="${delegateExpressionBean}" />

Here, the delegateExpressionBean is a bean that implements the JavaDelegate or FutureJavaDelegate interface, defined in, for example, the Spring container.

To specify a UEL method expression that should be evaluated, use the attribute **flowable:expression**.

    <serviceTask id="javaService"
                 name="My Java Service Task"
                 flowable:expression="#{printer.printMessage()}" />

Method printMessage (without parameters) will be called on the named object named printer.

It’s also possible to pass parameters with a method used in the expression.

    <serviceTask id="javaService"
                 name="My Java Service Task"
                 flowable:expression="#{printer.printMessage(execution, myVar)}" />

Method printMessage will be called on the object named printer. The first parameter passed is the DelegateExecution, which is available in the expression context, by default, available as execution. The second parameter passed is the value of the variable with name myVar in the current execution.

Note: When the execution of the method defined in **flowable:expression** takes longer time to execute it is possible to return a `CompletableFuture<?>`.
When this is used then other parallel flows can be executed in the same time.

To specify a UEL value expression that should be evaluated, use the attribute **flowable:expression**.

    <serviceTask id="javaService"
                 name="My Java Service Task"
                 flowable:expression="#{split.ready}" />

The getter method of property ready, getReady (without parameters), will be called on the named bean called split. The named objects are resolved in the execution’s process variables and (if applicable) in the Spring context.

#### Implementation

To implement a class that can be called during process execution, the class needs to implement the *org.flowable.engine.delegate.JavaDelegate* interface and provide the required logic in the *execute* method. When process execution arrives at this particular step, it will execute the logic defined in that method and leave the activity in the default BPMN 2.0 way.

Let’s create, for example, a Java class that can be used to change a process variable String to uppercase. This class needs to implement the *org.flowable.engine.delegate.JavaDelegate* interface, which requires us to implement the *execute(DelegateExecution)* method. It’s this operation that will be called by the engine and which needs to contain the business logic. Process instance information, such as process variables, can be accessed and manipulated through the [DelegateExecution](http://www.flowable.org/javadocs/org/flowable/engine/delegate/DelegateExecution.html) interface (click on the link for a detailed Javadoc of its operations).

    public class ToUppercase implements JavaDelegate {

      public void execute(DelegateExecution execution) {
        String var = (String) execution.getVariable("input");
        var = var.toUpperCase();
        execution.setVariable("input", var);
      }

    }

Note: there will be **only one instance of the Java class created for the serviceTask on which it is defined**. All process instances share the same class instance that will be used to call *execute(DelegateExecution)*. This means that the class must not use any member variables and must be thread-safe, as it can be executed simultaneously from different threads. This also influences the way [Field injection](bpmn/ch07b-BPMN-Constructs.md#field-injection) is handled.

The classes that are referenced in the process definition (by using flowable:class) are **NOT instantiated during deployment**. Only when a process execution arrives for the first time at the point in the process where the class is used, an instance of that class will be created. If the class cannot be found, an FlowableException will be thrown. The reasoning for this is that the environment (and more specifically, the *classpath*) when you are deploying is often different from the actual runtime environment. For example, when using *ant* or the business archive upload in the Flowable app to deploy processes, the classpath will not automatically contain the referenced classes.

In case the execution takes longer it is possible to delegate that work on a different thread, but still continue executing parallel activities.
In order to do this the *org.flowable.engine.delegate.FutureJavaDelegate* needs to be implemented.
This is a more advanced interface and special care needs to be done in order for data to be set on the `DelegateExecution` and to take care about the transaction boundaries.

```java
public class LongRunningJavaDelegate implements FutureJavaDelegate<String> {

    public CompletableFuture<String> execute(DelegateExecution execution, AsyncTaskInvoker taskInvoker) {
        // This is running in the same transaction as the process instance and is still possible to set and extract data from the execution
        String input = (String) execution.getVariable("input");
        // The taskInvoker is a common invoker provided by Flowable that can be used to submit complex executions on a new thread.
        // However, you don't have to use it, you can use your own custom ExecutorService or return a CompletableFuture from your own services.
        return taskInvoker.submit(() -> {
            // This is running on a new thread. The execution shouldn't be used here.
            // There is also no transaction here. In case a new transaction is needed, then it should be managed by your own services
            // Perform some complex logic that takes some time, e.g. invoking an external service
            return "done";
        });
    }

    public void afterExecution(DelegateExecution execution, String executionData) {
        // This is running in the same transaction and thread as the process instance and data can be set on the execution
        execution.setVariable("longRunningResult", executionData);
    }
}
```

There are also 2 other interfaces that can be used in to simplify your own implementation: 
* *org.flowable.engine.delegate.FlowableFutureJavaDelegate*, in which the default (or configured) AsyncTaskInvoker will be used, simplifying the logic.
* *org.flowable.engine.delegate.MapBasedFlowableFutureJavaDelegate*, which simplifies the passing of input and output further by using a ReadOnlyDelegateExecution and a Map respectively.

The same implementation with the other interfaces looks like:

```java
public class LongRunningJavaDelegate implements FlowableFutureJavaDelegate<String, String> {


    public String prepareExecutionData(DelegateExecution execution) {
        // This is running in the same transaction and thread as the process instance.
        // The execution can be used
        return execution.getVariable("input");
    }

    public String execute(String inputData) {
        // This is running on a new thread. The execution shouldn't be used here.
        // There is also no transaction here. In case a new transaction is needed, then it should be managed by your own services
        // Perform some complex logic that takes some time, e.g. invoking an external service
        return "done";
    }

    public void afterExecution(DelegateExecution execution, String executionData) {
        // This is running in the same transaction and thread as the process instance and data can be set on the execution
        execution.setVariable("longRunningResult", executionData);
    }
}
```

```java
public class LongRunningJavaDelegate implements MapBasedFlowableFutureJavaDelegate {

    public Map<String, Object> execute(ReadOnlyDelegateExecution execution) {
        // The execution is a read only snapshot of the delegate execution
        // This is running on a new thread. The execution shouldn't be used here.
        // There is also no transaction here. In case a new transaction is needed, then it should be managed by your own services
        // Perform some complex logic that takes some time, e.g. invoking an external service
        Map<String, Object> result = new HashMap<>();
        result.put("longRunningResult", "done");
        // All the values from the returned map will be set on the execution
        return result;
    }
}
```

Note: the same rules and logic that applied for the `JavaDelegate` applies for the `FutureJavaDelegate` as well. 
Keep in mind that when using field expression inject the evaluation of the expression should only be done before or after the execution is done (on the same thread as the process instance).

[\[INTERNAL: non-public implementation classes\]](../oss-introduction.md#internal-implementation-classes) It is also possible to provide a class that implements the *org.flowable.engine.impl.delegate.ActivityBehavior* interface. Implementations then have access to more powerful engine functionality, for example, to influence the control flow of the process. Note however that this is not a very good practice and should be avoided as much as possible. So, it is advisable to use the *ActivityBehavior* interface only for advanced use cases and if you know exactly what you’re doing.

#### Field Injection

It’s possible to inject values into the fields of the delegated classes. The following types of injection are supported:

-   Fixed string values

-   Expressions

If available, the value is injected through a public setter method on your delegated class, following the Java Bean naming conventions (for example, field firstName has setter setFirstName(...)). If no setter is available for that field, the value of the private member will be set on the delegate. SecurityManagers in some environments don’t allow modification of private fields, so it’s safer to expose a public setter-method for the fields you want to have injected.

**Regardless of the type of value declared in the process-definition, the type of the setter/private field on the injection target should always be org.flowable.engine.delegate.Expression. When the expression is resolved, it can be cast to the appropriate type.**

Field injection is supported when using the *'flowable:class'* attribute. Field injection is also possible when using the *flowable:delegateExpression* attribute, however special rules with regards to thread-safety apply (see next section).

The following code snippet shows how to inject a constant value into a field declared on the class. Note that we need to **declare an 'extensionElements' XML element before the actual field injection declarations**, which is a requirement of the BPMN 2.0 XML Schema.

    <serviceTask id="javaService"
        name="Java service invocation"
        flowable:class="org.flowable.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
        <extensionElements>
          <flowable:field name="text" stringValue="Hello World" />
      </extensionElements>
    </serviceTask>

The class ToUpperCaseFieldInjected has a field text that is of type org.flowable.engine.delegate.Expression. When calling text.getValue(execution), the configured string value Hello World will be returned:

    public class ToUpperCaseFieldInjected implements JavaDelegate {

      private Expression text;

      public void execute(DelegateExecution execution) {
        execution.setVariable("var", ((String)text.getValue(execution)).toUpperCase());
      }

    }

Alternatively, for long texts (for example, an inline e-mail) the *'flowable:string'* sub element can be used:

    <serviceTask id="javaService"
        name="Java service invocation"
        flowable:class="org.flowable.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
      <extensionElements>
        <flowable:field name="text">
            <flowable:string>
              This is a long string with a lot of words and potentially way longer even!
          </flowable:string>
        </flowable:field>
      </extensionElements>
    </serviceTask>

To inject values that are dynamically resolved at runtime, expressions can be used. Those expressions can use process variables or Spring defined beans (if Spring is used). As noted in [Service Task Implementation](bpmn/ch07b-BPMN-Constructs.md#implementation), an instance of the Java class is shared among all process-instances in a service task when using the *flowable:class* attribute. To have dynamic injection of values in fields, you can inject value and method expressions in a org.flowable.engine.delegate.Expression that can be evaluated/invoked using the DelegateExecution passed in the execute method.

The example class below uses the injected expressions and resolves them using the current DelegateExecution. A *genderBean* method call is used while passing the *gender* variable. Full code and test can be found in org.flowable.examples.bpmn.servicetask.JavaServiceTaskTest.testExpressionFieldInjection

    <serviceTask id="javaService" name="Java service invocation"
      flowable:class="org.flowable.examples.bpmn.servicetask.ReverseStringsFieldInjected">

      <extensionElements>
        <flowable:field name="text1">
          <flowable:expression>${genderBean.getGenderString(gender)}</flowable:expression>
        </flowable:field>
        <flowable:field name="text2">
           <flowable:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</flowable:expression>
        </flowable:field>
      </ extensionElements>
    </ serviceTask>

    public class ReverseStringsFieldInjected implements JavaDelegate {

      private Expression text1;
      private Expression text2;

      public void execute(DelegateExecution execution) {
        String value1 = (String) text1.getValue(execution);
        execution.setVariable("var1", new StringBuffer(value1).reverse().toString());

        String value2 = (String) text2.getValue(execution);
        execution.setVariable("var2", new StringBuffer(value2).reverse().toString());
      }
    }

Alternatively, you can also set the expressions as an attribute instead of a child-element, to make the XML less verbose.

    <flowable:field name="text1" expression="${genderBean.getGenderString(gender)}" />
    <flowable:field name="text1" expression="Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}" />

#### Field injection and thread safety

In general, using service tasks with Java delegates and field injections are thread-safe. However, there are a few situations where thread-safety is not guaranteed, depending on the setup or environment Flowable is running in.

With the *flowable:class* attribute, using field injection is always thread safe. For each service task that references a certain class, a new instance will be instantiated and fields will be injected once when the instance is created. Reusing the same class multiple times in different tasks or process definitions is no problem.

When using the *flowable:expression* attribute, use of field injection is not possible. Parameters are passed via method calls and these are always thread-safe.

When using the *flowable:delegateExpression* attribute, the thread-safety of the delegate instance will depend on how the expression is resolved. If the delegate expression is reused in various tasks or process definitions, and the expression always returns the same instance, using field injection **is not thread-safe**. Let’s look at a few examples to clarify.

Suppose the expression is *${factory.createDelegate(someVariable)}*, where factory is a Java bean known to the engine (for example, a Spring bean when using the Spring integration) that creates a new instance each time the expression is resolved. When using field injection in this case, there is no problem with regards to thread-safety: each time the expression is resolved, the fields are injected in this new instance.

However, suppose the expression is *${someJavaDelegateBean}* that resolves to an implementation of the JavaDelegate class and we’re running in an environment that creates singleton instances of each bean (such as Spring, but many others too). When using this expression in different tasks or process definitions, the expression will always be resolved to the same instance. In this case, using field injection is not thread-safe. For example:

    <serviceTask id="serviceTask1" flowable:delegateExpression="${someJavaDelegateBean}">
        <extensionElements>
            <flowable:field name="someField" expression="${input * 2}"/>
        </extensionElements>
    </serviceTask>

    

    <serviceTask id="serviceTask2" flowable:delegateExpression="${someJavaDelegateBean}">
        <extensionElements>
            <flowable:field name="someField" expression="${input * 2000}"/>
        </extensionElements>
    </serviceTask>

This example snippet has two service tasks that use the same delegate expression, but inject different values for the *Expression* field. **If the expression resolves to the same instance, there can be race conditions in concurrent scenarios** when it comes to injecting the field *someField* when the processes are executed.

The easiest solution to solve this is to either:

-   rewrite the Java delegate to use an expression and passing the required data to the delegate via a method arguments.

-   return a new instance of the delegate class each time the delegate expression is resolved. For example, when using Spring, this means that the scope of the bean must be set to **prototype** (such as by adding the @Scope(SCOPE\_PROTOTYPE) annotation to the delegate class).

As of Flowable v5.22, the process engine configuration can be set in a way to disable the use of field injection on delegate expressions, by setting the value of the *delegateExpressionFieldInjectionMode* property (which takes one of the values in the *org.flowable.engine.imp.cfg.DelegateExpressionFieldInjectionMode* enum).

Following settings are possible:

-   **DISABLED** : fully disables field injection when using delegate expressions. No field injection will be attempted. This is the safest mode when it comes to thread-safety.

-   **COMPATIBILITY**: in this mode, the behavior will be exactly as it was before v5.21: field injection is possible when using delegate expressions and an exception will be thrown when the fields are not defined on the delegate class. This is, of course, the least safe mode with regards to thread-safety, but it can be necessary for backwards compatibility or can be used safely when the delegate expression is used only on one task in a set of process definitions (and thus no concurrent race conditions can happen).

-   **MIXED**: Allows injection when using delegateExpressions, but will not throw an exception when the fields are not defined on the delegate. This allows for mixed behaviors, where some delegates have injection (for example, because they are not singletons) and some don’t.

-   **The default mode for Flowable version 5.x is COMPATIBILITY.**

-   **The default mode for Flowable version 6.x is MIXED.**

As an example, suppose that we’re using *MIXED* mode and we’re using Spring integration. Suppose that we have the following beans in the Spring configuration:

    <bean id="singletonDelegateExpressionBean"
      class="org.flowable.spring.test.fieldinjection.SingletonDelegateExpressionBean" />

    <bean id="prototypeDelegateExpressionBean"
      class="org.flowable.spring.test.fieldinjection.PrototypeDelegateExpressionBean"
      scope="prototype" />

The first bean is a regular Spring bean and thus a singleton. The second one has *prototype* as scope, and the Spring container will return a new instance every time the bean is requested.

Given the following process definition:

    <serviceTask id="serviceTask1" flowable:delegateExpression="${prototypeDelegateExpressionBean}">
      <extensionElements>
        <flowable:field name="fieldA" expression="${input * 2}"/>
        <flowable:field name="fieldB" expression="${1 + 1}"/>
        <flowable:field name="resultVariableName" stringValue="resultServiceTask1"/>
      </extensionElements>
    </serviceTask>

    <serviceTask id="serviceTask2" flowable:delegateExpression="${prototypeDelegateExpressionBean}">
      <extensionElements>
        <flowable:field name="fieldA" expression="${123}"/>
        <flowable:field name="fieldB" expression="${456}"/>
        <flowable:field name="resultVariableName" stringValue="resultServiceTask2"/>
      </extensionElements>
    </serviceTask>

    <serviceTask id="serviceTask3" flowable:delegateExpression="${singletonDelegateExpressionBean}">
      <extensionElements>
        <flowable:field name="fieldA" expression="${input * 2}"/>
        <flowable:field name="fieldB" expression="${1 + 1}"/>
        <flowable:field name="resultVariableName" stringValue="resultServiceTask1"/>
      </extensionElements>
    </serviceTask>

    <serviceTask id="serviceTask4" flowable:delegateExpression="${singletonDelegateExpressionBean}">
      <extensionElements>
        <flowable:field name="fieldA" expression="${123}"/>
        <flowable:field name="fieldB" expression="${456}"/>
        <flowable:field name="resultVariableName" stringValue="resultServiceTask2"/>
      </extensionElements>
    </serviceTask>

We’ve got four service tasks, where the first and the second use the *${prototypeDelegateExpressionBean}* delegate expression and the third and fourth use the *${singletonDelegateExpressionBean}* delegate expression.

Let’s look at the prototype bean first:

    public class PrototypeDelegateExpressionBean implements JavaDelegate {

      public static AtomicInteger INSTANCE_COUNT = new AtomicInteger(0);

      private Expression fieldA;
      private Expression fieldB;
      private Expression resultVariableName;

      public PrototypeDelegateExpressionBean() {
        INSTANCE_COUNT.incrementAndGet();
      }

      @Override
      public void execute(DelegateExecution execution) {

        Number fieldAValue = (Number) fieldA.getValue(execution);
        Number fieldValueB = (Number) fieldB.getValue(execution);

        int result = fieldAValue.intValue() + fieldValueB.intValue();
        execution.setVariable(resultVariableName.getValue(execution).toString(), result);
      }

    }

When we check the *INSTANCE\_COUNT* after running a process instance of the process definition above, we’ll get *two* back, as a new instance is created every time *${prototypeDelegateExpressionBean}* is resolved. Fields can be injected without any problem here and we can see the three *Expression* member fields here.

The singleton bean, however, looks slightly different:

    public class SingletonDelegateExpressionBean implements JavaDelegate {

      public static AtomicInteger INSTANCE_COUNT = new AtomicInteger(0);

      public SingletonDelegateExpressionBean() {
        INSTANCE_COUNT.incrementAndGet();
      }

      @Override
      public void execute(DelegateExecution execution) {

        Expression fieldAExpression = DelegateHelper.getFieldExpression(execution, "fieldA");
        Number fieldA = (Number) fieldAExpression.getValue(execution);

        Expression fieldBExpression = DelegateHelper.getFieldExpression(execution, "fieldB");
        Number fieldB = (Number) fieldBExpression.getValue(execution);

        int result = fieldA.intValue() + fieldB.intValue();

        String resultVariableName = DelegateHelper.getFieldExpression(execution,
            "resultVariableName").getValue(execution).toString();
        execution.setVariable(resultVariableName, result);
      }

    }

The *INSTANCE\_COUNT* will always be *one* here, as it is a singleton. In this delegate, there are no *Expression* member fields. This is possible as we’re running in *MIXED* mode. In *COMPATIBILITY* mode, this would throw an exception as it expects the member fields to be there. *DISABLED* mode would also work for this bean, but it would disallow the use the prototype bean above that does use field injection.

In this delegate code, the **org.flowable.engine.delegate.DelegateHelper** class is used, which has some useful utility methods to execute the same logic, but in a thread-safe way when the delegate is a singleton. Instead of injecting the *Expression*, it is fetched via the *getFieldExpression* method. This means that when it comes to the service task XML, the fields are defined exactly the same as for the singleton bean. If you look at the XML snippet above, you can see they are equal in definition and only the implementation logic differs.

Technical note: the *getFieldExpression* will introspect the BpmnModel and create the Expression on the fly when the method is executed, making it thread-safe.

-   For Flowable v5.x, the DelegateHelper cannot be used for an *ExecutionListener* or *TaskListener* (due to an architectural flaw). To make thread-safe instances of those listeners, use either an expression or make sure a new instance is created every time the delegate expression is resolved.

-   For Flowable V6.x the DelegateHelper does work in *ExecutionListener* and *TaskListener* implementations. For example, in V6.x, the following code can be written, using the **DelegateHelper**:



    <extensionElements>
      <flowable:executionListener
          delegateExpression="${testExecutionListener}" event="start">
        <flowable:field name="input" expression="${startValue}" />
        <flowable:field name="resultVar" stringValue="processStartValue" />
      </flowable:executionListener>
    </extensionElements>

Where *testExecutionListener* resolves to an instance implementing the ExecutionListener interface:

    @Component("testExecutionListener")
    public class TestExecutionListener implements ExecutionListener {

      @Override
      public void notify(DelegateExecution execution) {
        Expression inputExpression = DelegateHelper.getFieldExpression(execution, "input");
        Number input = (Number) inputExpression.getValue(execution);

        int result = input.intValue() * 100;

        Expression resultVarExpression = DelegateHelper.getFieldExpression(execution, "resultVar");
        execution.setVariable(resultVarExpression.getValue(execution).toString(), result);
      }

    }

#### Service task results

The return value of a service execution (for service task using expression only) can be assigned to an existing or to a new process variable by specifying the process variable name as a literal value for the *'flowable: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.
If *\`flowable:useLocalScopeForResultVariable'* is used, then the variable will be assigned to a local variable.
When a result variable name is not specified, the service execution result value gets ignored.

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

In the example above, the result of the service execution (the return value of the *'doSomething()'* method invocation on an object is made available under the name *'myService'*, either in the process variables or as a Spring bean) is set to the process variable named *'myVar'* after the service execution completes.

Note: When the method returns `CompletableFuture<?>` then the result of the future will be set in the result variable.

#### Triggerable

A common pattern is to trigger an external serviced by sending a JMS message or do a HTTP call and have the process instance go into a wait state. Then at some point the external service will return a response and the process instance continues to the next activity. With default BPMN you would need to model a service task and a receive task. This however introduces some racing conditions because the external service response could be returned before the process instance is persisted and the receive task is active. To solve this, Flowable supports a triggerable attribute on a service task that transforms the single service task in a task that will execute the service logic and then will wait for an external trigger before it continues to the next activity in the process definition. If the async attribute is also set to true for a triggerable service task, the process instance state is first persisted and then the service task logic will be executed in an async job. In BPMN XML an async triggerable service task would be implemented like this:

    <serviceTask id="aTriggerableServiceTask"
        flowable:expression="#{myService.doSomething()}"
        flowable:triggerable="true"
        flowable:async="true" />

When the external service wants to trigger the waiting process instance again, this can be done synchronously and asynchronously. To prevent optimistic lock exceptions, the asynchronous trigger would be the best solution. By default an async job is exclusive, which means that the process instance will be locked and it’s guaranteed that no other activity on the process instance can interfere with the trigger logic. The RuntimeService triggerAsync methods can be used to trigger the waiting process instance in an asynchronous way. Of course it’s also still possible to do this in an synchronous way using the trigger methods of the RuntimeService.

#### Handling exceptions

When custom logic is executed, it is often necessary to catch certain business exceptions and handle them inside the surrounding process. Flowable provides different options to do that.

##### Throwing BPMN Errors

It is possible to throw BPMN Errors from user code inside Service Tasks or Script Tasks. In order to do this, a special FlowableException called *BpmnError* can be thrown in JavaDelegates, FutureJavaDelegates, scripts, expressions and delegate expressions. The engine will catch this exception and forward it to an appropriate error handler, for example, a Boundary Error Event or an Error Event Sub-Process.

    public class ThrowBpmnErrorDelegate implements JavaDelegate {

      public void execute(DelegateExecution execution) throws Exception {
        try {
          executeBusinessLogic();
        } catch (BusinessException e) {
          throw new BpmnError("BusinessExceptionOccurred");
        }
      }

    }

The constructor argument is an error code, which will be used to determine the error handler that is responsible for the error. See [Boundary Error Event](bpmn/ch07b-BPMN-Constructs.md#error-boundary-event) for information on how to catch a BPMN Error.

This mechanism should be used **only for business faults** that will be handled by a Boundary Error Event or Error Event Sub-Process modeled in the process definition. Technical errors should be represented by other exception types and are not usually handled inside a process.

##### Exception mapping

It’s also possible to directly map a Java exception to business exception by using the mapException extension. Single mapping is the simplest form:

    <serviceTask id="servicetask1" name="Service Task" flowable:class="...">
      <extensionElements>
        <flowable:mapException
              errorCode="myErrorCode1">org.flowable.SomeException</flowable:mapException>
      </extensionElements>
    </serviceTask>

In above code, if an instance of org.flowable.SomeException is thrown in the service task, it will be caught and converted to a BPMN exception with the given errorCode. From this point on, it will be handled exactly like a normal BPMN exception.
Any other exception will be treated as if there is no mapping in place. It will be propagated to the API caller.

One can map all the child exceptions of a certain exception in a single line by using includeChildExceptions attribute.

    <serviceTask id="servicetask1" name="Service Task" flowable:class="...">
      <extensionElements>
        <flowable:mapException errorCode="myErrorCode1"
               includeChildExceptions="true">org.flowable.SomeException</flowable:mapException>
      </extensionElements>
    </serviceTask>

The above code will cause Flowable to convert any direct or indirect descendent of SomeException to a BPMN error with the given error code.
includeChildExceptions will be considered "false" when not given.

The most generic mapping is a default map, which is a map with no class. It will match any Java exception:

    <serviceTask id="servicetask1" name="Service Task" flowable:class="...">
      <extensionElements>
        <flowable:mapException errorCode="myErrorCode1"/>
      </extensionElements>
    </serviceTask>

The mappings are checked in order, from top to bottom, and the first match found will be followed, except for the default map. The default map is selected only after all maps have been checked unsuccessfully.
Only the first map with no class will be considered as a default map. includeChildExceptions is ignored with a default map.

##### Exception Sequence Flow

[\[INTERNAL: non-public implementation classes\]](internal)

Another option is to route process execution through a different path when some exception occurs. The following example shows how this is done.

    <serviceTask id="javaService"
      name="Java service invocation"
      flowable:class="org.flowable.ThrowsExceptionBehavior">
    </serviceTask>

    <sequenceFlow id="no-exception" sourceRef="javaService" targetRef="theEnd" />
    <sequenceFlow id="exception" sourceRef="javaService" targetRef="fixException" />

Here, the service task has two outgoing sequence flows, named exception and no-exception. The sequence flow ID will be used to direct process flow if there’s an exception:

    public class ThrowsExceptionBehavior implements ActivityBehavior {

      public void execute(DelegateExecution execution) {
        String var = (String) execution.getVariable("var");

        String sequenceFlowToTake = null;
        try {
          executeLogic(var);
          sequenceFlowToTake = "no-exception";
        } catch (Exception e) {
          sequenceFlowToTake = "exception";
        }
        DelegateHelper.leaveDelegate(execution, sequenceFlowToTake);
      }

    }

#### Using a Flowable service from within a JavaDelegate

For some use cases, it might be necessary to use the Flowable services from within a Java service task (for example, starting a process instance through the RuntimeService, if the callActivity doesn’t suit your needs).

    public class StartProcessInstanceTestDelegate implements JavaDelegate {

      public void execute(DelegateExecution execution) throws Exception {
        RuntimeService runtimeService = Context.getProcessEngineConfiguration().getRuntimeService();
        runtimeService.startProcessInstanceByKey("myProcess");
      }

    }

All of the Flowable service APIs are available through this interface.

All data changes that occur as an effect of using these API calls will be part of the current transaction. This also works in environments with dependency injection, such as Spring and CDI with or without a JTA enabled datasource. For example, the following snippet of code will do the same as the snippet above, but now the RuntimeService is injected rather than being fetched through the *org.flowable.engine.EngineServices* interface.

    @Component("startProcessInstanceDelegate")
    public class StartProcessInstanceTestDelegateWithInjection {

        @Autowired
        private RuntimeService runtimeService;

        public void startProcess() {
          runtimeService.startProcessInstanceByKey("oneTaskProcess");
        }

    }

**Important technical note:** because the service call is being done as part of the current transaction, any data that was produced or altered *before* the service task is executed is not yet flushed to the database. All API calls work on the database data, which means that these uncommitted changes are not 'visible' within the API call of the service task.

### Web Service Task

#### Description

A Web Service task is used to synchronously invoke an external Web service.

#### Graphical Notation

A Web Service task is visualized in the same way as a Java service task.



#### XML representation

To use a Web service we need to import its operations and complex types. This can be done automatically by using the import tag pointing to the WSDL of the Web service:

    <import importType="http://schemas.xmlsoap.org/wsdl/"
        location="http://localhost:63081/counter?wsdl"
        namespace="http://webservice.flowable.org/" />

The previous declaration tells Flowable to import the definitions, but it doesn’t create the item definitions and messages for you. Let’s suppose we want to invoke a specific method called 'prettyPrint', therefore we will need to create the corresponding message and item definitions for the request and response messages:

    <message id="prettyPrintCountRequestMessage" itemRef="tns:prettyPrintCountRequestItem" />
    <message id="prettyPrintCountResponseMessage" itemRef="tns:prettyPrintCountResponseItem" />

    <itemDefinition id="prettyPrintCountRequestItem" structureRef="counter:prettyPrintCount" />
    <itemDefinition id="prettyPrintCountResponseItem" structureRef="counter:prettyPrintCountResponse" />

Before declaring the service task, we have to define the BPMN interfaces and operations that actually reference the Web service ones. Basically, we define and 'interface' and the required 'operations'. For each operation we reuse the previous defined message for 'in' and 'out'. For example, the following declaration defines the 'counter' interface and the 'prettyPrintCountOperation' operation:

    <interface name="Counter Interface" implementationRef="counter:Counter">
        <operation id="prettyPrintCountOperation" name="prettyPrintCount Operation"
                implementationRef="counter:prettyPrintCount">
            <inMessageRef>tns:prettyPrintCountRequestMessage</inMessageRef>
            <outMessageRef>tns:prettyPrintCountResponseMessage</outMessageRef>
        </operation>
    </interface>

Then we can declare a Web Service Task by using the \#\#WebService implementation and a reference to the Web service operation.

    <serviceTask id="webService"
        name="Web service invocation"
        implementation="##WebService"
        operationRef="tns:prettyPrintCountOperation">

#### Web Service Task IO Specification

Unless we are using the simplistic approach for data input and output associations (see below), each Web Service Task needs to declare an IO Specification that specifies the inputs and outputs of the task. The approach is pretty straightforward and BPMN 2.0 complaint, for our prettyPrint example we define the input and output sets according to the previously declared item definitions:

    <ioSpecification>
        <dataInput itemSubjectRef="tns:prettyPrintCountRequestItem" id="dataInputOfServiceTask" />
        <dataOutput itemSubjectRef="tns:prettyPrintCountResponseItem" id="dataOutputOfServiceTask" />
        <inputSet>
            <dataInputRefs>dataInputOfServiceTask</dataInputRefs>
        </inputSet>
        <outputSet>
            <dataOutputRefs>dataOutputOfServiceTask</dataOutputRefs>
        </outputSet>
    </ioSpecification>

#### Web Service Task data input associations

There are 2 ways of specifying data input associations:

-   Using expressions

-   Using the simplistic approach

To specify the data input association using expressions, we need to define the source and target items and specify the corresponding assignments between the fields of each item. In the following example we assign prefix and suffix fields for the items:

    <dataInputAssociation>
        <sourceRef>dataInputOfProcess</sourceRef>
        <targetRef>dataInputOfServiceTask</targetRef>
        <assignment>
            <from>${dataInputOfProcess.prefix}</from>
            <to>${dataInputOfServiceTask.prefix}</to>
        </assignment>
        <assignment>
            <from>${dataInputOfProcess.suffix}</from>
            <to>${dataInputOfServiceTask.suffix}</to>
        </assignment>
    </dataInputAssociation>

On the other hand, we can use the simplistic approach, which is much more straightforward. The 'sourceRef' element is a Flowable variable name and the 'targetRef' element is a property of the item definition. In the following example, we assign the 'prefix' field the value of the variable 'PrefixVariable', and the 'suffix' field the value of the variable 'SuffixVariable'.

    <dataInputAssociation>
        <sourceRef>PrefixVariable</sourceRef>
        <targetRef>prefix</targetRef>
    </dataInputAssociation>
    <dataInputAssociation>
        <sourceRef>SuffixVariable</sourceRef>
        <targetRef>suffix</targetRef>
    </dataInputAssociation>

#### Web Service Task data output associations

There are 2 ways of specifying data out associations:

-   Using expressions

-   Using the simplistic approach

To specify the data out association using expressions we need to define the target variable and the source expression. The approach is pretty straightforward and similar to data input associations:

    <dataOutputAssociation>
        <targetRef>dataOutputOfProcess</targetRef>
        <transformation>${dataOutputOfServiceTask.prettyPrint}</transformation>
    </dataOutputAssociation>

Alternatively, we can use the simplistic approach that is much more straightforward. The 'sourceRef' element is a property of the item definition and the 'targetRef' element is a Flowable variable name. The approach is pretty simple and similar to data input associations:

    <dataOutputAssociation>
        <sourceRef>prettyPrint</sourceRef>
        <targetRef>OutputVariable</targetRef>
    </dataOutputAssociation>

### Business Rule Task

#### Description

A Business Rule task is used to synchronously execute one or more rules. Flowable uses Drools Expert, the Drools rule engine to execute business rules. Currently, the .drl files containing the business rules have to be deployed together with the process definition that defines a business rule task to execute those rules. This means that all .drl files that are used in a process have to be packaged in the process BAR file, as for task forms and so on. For more information about creating business rules for Drools Expert, please refer to the Drools documentation at [JBoss Drools](http://www.jboss.org/drools/documentation)

If you want to plug in your own implementation of the rule task, for example, because you want to use Drools differently or you want to use a completely different rule engine, then you can use the class or expression attribute on the BusinessRuleTask and it will behave exactly like a [ServiceTask](bpmn/ch07b-BPMN-Constructs.md#java-service-task)

#### Graphical Notation

A Business Rule task is visualized the with a table icon.



#### XML representation

To execute one or more business rules that are deployed in the same BAR file as the process definition, we need to define the input and result variables. For the input variable definition, a list of process variables can be defined separated by a comma. The output variable definition can only contain one variable name that will be used to store the output objects of the executed business rules in a process variable. Note that the result variable will contain a List of objects. If no result variable name is specified by default, org.flowable.engine.rules.OUTPUT is used.

The following business rule task executes all business rules deployed with the process definition:

    <process id="simpleBusinessRuleProcess">

      <startEvent id="theStart" />
      <sequenceFlow sourceRef="theStart" targetRef="businessRuleTask" />

      <businessRuleTask id="businessRuleTask" flowable:ruleVariablesInput="${order}"
          flowable:resultVariable="rulesOutput" />

      <sequenceFlow sourceRef="businessRuleTask" targetRef="theEnd" />

      <endEvent id="theEnd" />

    </process>

The business rule task can also be configured to execute only a defined set of rules from the deployed .drl files. A list of rule names separated by a comma must be specified for this.

    <businessRuleTask id="businessRuleTask" flowable:ruleVariablesInput="${order}"
          flowable:rules="rule1, rule2" />

In this case only rule1 and rule2 are executed.

You can also define a list of rules that should be excluded from execution.

    <businessRuleTask id="businessRuleTask" flowable:ruleVariablesInput="${order}"
          flowable:rules="rule1, rule2" exclude="true" />

In this case all rules deployed in the same BAR file as the process definition will be executed, except for rule1 and rule2.

As mentioned earlier another option is to hook in the implementation of the BusinessRuleTask yourself:

    <businessRuleTask id="businessRuleTask" flowable:class="${MyRuleServiceDelegate}" />

Now the BusinessRuleTask behaves exactly like a ServiceTask, but still keeps the BusinessRuleTask icon to visualize that we are doing business rule processing here.

### Email Task

Flowable allows you to enhance business processes with automatic mail service tasks that send e-mails to one or more recipients, including support for cc, bcc, HTML content, and so on. Note that the mail task is **not** an 'official' task of the BPMN 2.0 spec (and doesn’t have a dedicated icon as a consequence). Hence, in Flowable the mail task is implemented as a dedicated service task.

#### Mail server configuration

The Flowable engine sends e-mails trough an external mail server with SMTP capabilities. To actually send e-mails, the engine needs to know how to reach the mail server. The following properties can be set in the *flowable.cfg.xml* configuration file:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Property</th>
<th>Required?</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>mailServerHost</p></td>
<td><p>no</p></td>
<td><p>The hostname of your mail server (for example, mail.mycorp.com). Default is localhost</p></td>
</tr>
<tr class="even">
<td><p>mailServerPort</p></td>
<td><p>yes, if not on the default port</p></td>
<td><p>The port for SMTP traffic on the mail server. The default is <em>25</em></p></td>
</tr>
<tr class="odd">
<td><p>mailServerForceTo</p></td>
<td><p>no</p></td>
<td><p>If set it will be used as a replacement of the configured to, cc and / or bcc in the Mail Task when sending out emails.</p></td>
</tr>
<tr class="even">
<td><p>mailServerDefaultFrom</p></td>
<td><p>no</p></td>
<td><p>The default e-mail address of the sender of e-mails, when none is provided by the user. By default this is <em>flowable@localhost</em></p></td>
</tr>
<tr class="odd">
<td><p>mailServerUsername</p></td>
<td><p>if applicable for your server</p></td>
<td><p>Some mail servers require credentials for sending e-mail. By default not set.</p></td>
</tr>
<tr class="even">
<td><p>mailServerPassword</p></td>
<td><p>if applicable for your server</p></td>
<td><p>Some mail servers require credentials for sending e-mail. By default not set.</p></td>
</tr>
<tr class="odd">
<td><p>mailServerUseSSL</p></td>
<td><p>if applicable for your server</p></td>
<td><p>Some mail servers require ssl communication. By default set to false.</p></td>
</tr>
<tr class="even">
<td><p>mailServerUseTLS</p></td>
<td><p>if applicable for your server</p></td>
<td><p>Some mail servers (for instance gmail) require TLS communication. By default set to false.</p></td>
</tr>
</tbody>
</table>

#### Defining an Email Task

The Email task is implemented as a dedicated [Service Task](bpmn/ch07b-BPMN-Constructs.md#java-service-task) and is defined by setting *'mail'* for the *type* of the service task.

    <serviceTask id="sendMail" flowable:type="mail">

The Email task is configured by [field injection](bpmn/ch07b-BPMN-Constructs.md#field-injection). All the values for these properties can contain EL expression, which are resolved at runtime during process execution. The following properties can be set:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Property</th>
<th>Required?</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>to</p></td>
<td><p>yes</p></td>
<td><p>The recipients of the e-mail. Multiple recipients are defined in a comma-separated list</p></td>
</tr>
<tr class="even">
<td><p>from</p></td>
<td><p>no</p></td>
<td><p>The sender e-mail address. If not provided, the <a href="#bpmnEmailTaskServerConfiguration">default configured</a> from address is used.</p></td>
</tr>
<tr class="odd">
<td><p>subject</p></td>
<td><p>no</p></td>
<td><p>The subject of the e-mail.</p></td>
</tr>
<tr class="even">
<td><p>cc</p></td>
<td><p>no</p></td>
<td><p>The cc’s of the e-mail. Multiple recipients are defined in a comma-separated list</p></td>
</tr>
<tr class="odd">
<td><p>bcc</p></td>
<td><p>no</p></td>
<td><p>The bcc’s of the e-mail. Multiple recipients are defined in a comma-separated list</p></td>
</tr>
<tr class="even">
<td><p>charset</p></td>
<td><p>no</p></td>
<td><p>Allows specification of the charset of the email, which is necessary for many
non-English languages.</p></td>
</tr>
<tr class="odd">
<td><p>html</p></td>
<td><p>no</p></td>
<td><p>A piece of HTML that is the content of the e-mail.</p></td>
</tr>
<tr class="even">
<td><p>text</p></td>
<td><p>no</p></td>
<td><p>The content of the e-mail, in case one needs to send plain, non-rich e-mails.
Can be used in combination with <em>html</em>, for e-mail clients
that don’t support rich content. The email client can then fall back to this text-only alternative.</p></td>
</tr>
<tr class="odd">
<td><p>htmlVar</p></td>
<td><p>no</p></td>
<td><p>The name of a process variable that holds the HTML that is the content of the e-mail. The key difference between this and <em>html</em> is that this content will have expressions replaced before being sent by the mail task.</p></td>
</tr>
<tr class="even">
<td><p>textVar</p></td>
<td><p>no</p></td>
<td><p>The name of a process variable that holds the plain text content of the e-mail. The key difference between this and <em>text</em> is that this content will have expressions replaced before being sent by the mail task.</p></td>
</tr>
<tr class="odd">
<td><p>ignoreException</p></td>
<td><p>no</p></td>
<td><p>Whether a failure when handling the e-mail is ignored rather than throw a FlowableException. By default this is set to false.</p></td>
</tr>
<tr class="even">
<td><p>exceptionVariableName</p></td>
<td><p>no</p></td>
<td><p>When email handling does not throw an exception because <em>ignoreException = true</em>, a variable with the given name is used to hold a failure message</p></td>
</tr>
</tbody>
</table>

#### Example usage

The following XML snippet shows an example of using the Email Task.

    <serviceTask id="sendMail" flowable:type="mail">
      <extensionElements>
        <flowable:field name="from" stringValue="order-shipping@thecompany.com" />
        <flowable:field name="to" expression="${recipient}" />
        <flowable:field name="subject" expression="Your order ${orderId} has been shipped" />
        <flowable:field name="html">
          <flowable:expression>
            <![CDATA[
              <html>
                <body>
                  Hello ${male ? 'Mr.' : 'Mrs.' } ${recipientName},<br/><br/>

                  As of ${now}, your order has been <b>processed and shipped</b>.<br/><br/>

                  Kind regards,<br/>

                  TheCompany.
                </body>
              </html>
            ]]>
          </flowable:expression>
        </flowable:field>
      </extensionElements>
    </serviceTask>

### Http Task

The Http task allows to make HTTP requests, enhancing the integration features of Flowable. Note that Http task is not an 'official' task of the BPMN 2.0 spec (and doesn’t have a dedicated icon as a consequence). Hence, in Flowable, Http task is implemented as a dedicated service task.

#### Http Client configuration

The Flowable engine makes Http requests through a configurable Http Client. If none is set, default settings are used.

Example configuration:

      <bean id="processEngineConfiguration"
            class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        
        <property name="httpClientConfig" ref="httpClientConfig"/>
      </bean>

      <bean id="httpClientConfig" class="org.flowable.engine.cfg.HttpClientConfig">
        <property name="connectTimeout" value="5000"/>
        <property name="socketTimeout" value="5000"/>
        <property name="connectionRequestTimeout" value="5000"/>
        <property name="requestRetryLimit" value="5"/>
      </bean>

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Property</th>
<th>Required?</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>connectTimeout</p></td>
<td><p>no</p></td>
<td><p>Connection timeout in milliseconds.<br />
By default set to 5000.</p></td>
</tr>
<tr class="even">
<td><p>socketTimeout</p></td>
<td><p>no</p></td>
<td><p>Socket timeout in milliseconds.<br />
By default set to 5000.</p></td>
</tr>
<tr class="odd">
<td><p>connectionRequestTimeout</p></td>
<td><p>no</p></td>
<td><p>Connection request timeout in milliseconds.<br />
By default set to 5000.</p></td>
</tr>
<tr class="even">
<td><p>requestRetryLimit</p></td>
<td><p>no</p></td>
<td><p>Request retry limit ('0' means do not retry).<br />
By default set to 3.</p></td>
</tr>
<tr class="odd">
<td><p>disableCertVerify</p></td>
<td><p>no</p></td>
<td><p>Flag to disable SSL certificate verification.<br />
By default set to false.</p></td>
</tr>
</tbody>
</table>

#### Defining Http Task

The Http task is implemented as a dedicated [Service Task](bpmn/ch07b-BPMN-Constructs.md#java-service-task) and is defined by setting *'http'* for the *type* of the service task.

    <serviceTask id="httpGet" flowable:type="http">

It is possible to override the default Http Task behavior by providing a custom implementation.
Custom implementations should extend org.flowable.engine.impl.bpmn.http.DefaultBpmnHttpActivityDelegate and override the methods you need.

The field 'httpActivityBehaviorClass' should be set in the task definition (Default value for this field is 'org.flowable.engine.impl.bpmn.http.DefaultBpmnHttpActivityDelegate').

The http client is abstracted through `FlowableHttpClient`. The default implementation when using the `flowable-http` dependency is based on the Apache Http Client.
As Apache Http Client can be customized in many ways, all possible options are not used in the Http Client config.
There is also an implementation based on the Spring WebClient, which will be used when the Apache Http Client is not on the classpath.

To create a custom client refer to [Http Client builder](http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html)

    <serviceTask id="httpGet" flowable:type="http">
      <extensionElements>
        <flowable:field name="httpActivityBehaviorClass">
            <flowable:string>
              <![CDATA[org.example.flowable.HttpActivityBehaviorCustomImpl]]>
            </flowable:string>
        </flowable:field>
      </extensionElements>
    </serviceTask>

#### Http Task configuration

The Http task is configured by [field injection](bpmn/ch07b-BPMN-Constructs.md#field-injection). All the values for these properties can contain EL expression, which are resolved at runtime during execution. The following properties can be set:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Property</th>
<th>Required?</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>requestMethod</p></td>
<td><p>yes</p></td>
<td><p>Request method<br />
(GET,POST,PUT,DELETE).</p></td>
</tr>
<tr class="even">
<td><p>requestUrl</p></td>
<td><p>yes</p></td>
<td><p>Request URL<br />
(Example - <a href="http://flowable.org">http://flowable.org</a>).</p></td>
</tr>
<tr class="odd">
<td><p>requestHeaders</p></td>
<td><p>no</p></td>
<td><p>Line separated Http request headers.<br />
Example -<br />
Content-Type: application/json<br />
Authorization: Basic aGFRlc3Q=</p></td>
</tr>
<tr class="even">
<td><p>requestBody</p></td>
<td><p>no</p></td>
<td><p>Request body<br />
Example - ${sampleBody}</p></td>
</tr>
<tr class="odd">
<td><p>requestTimeout</p></td>
<td><p>no</p></td>
<td><p>Timeout in milliseconds for the request<br />
(Example - 5000).<br />
Default is '0', meaning no timeout.<br />
Please refer <a href="#bpmnHttpTaskClientConfiguration">Http Client configuration</a> for connection related timeouts.</p></td>
</tr>
<tr class="even">
<td><p>disallowRedirects</p></td>
<td><p>no</p></td>
<td><p>Flag to disallow Http redirects.<br />
Default is false.<br />
(Example - true).</p></td>
</tr>
<tr class="odd">
<td><p>failStatusCodes</p></td>
<td><p>no</p></td>
<td><p>Comma separated list of Http response status codes to fail the request and throw a FlowableException.<br />
Example: 400, 404, 500, 503<br />
Example: 400, 5XX</p></td>
</tr>
<tr class="even">
<td><p>handleStatusCodes</p></td>
<td><p>no</p></td>
<td><p>Comma separated list of status codes for which the task will throw BpmnError which can be caught by a boundary error event.<br />
The error code of the BpmnError is 'HTTP&lt;statuscode&gt;'.<br />
For example, 404 status code is set with error code 'HTTP404'.<br />
3XX status codes are thrown only if 'disallowRedirects' field is also set.<br />
Status codes in 'handleStatusCodes' override those in 'failStatusCodes' when they are set in both.<br />
Example: 400, 404, 500, 503<br />
Example: 3XX, 4XX, 5XX<br />
</p></td>
</tr>
<tr class="odd">
<td><p>ignoreException</p></td>
<td><p>no</p></td>
<td><p>Flag for ignoring the exceptions. The exception is caught and stored as a variable with the name '&lt;taskId&gt;ErrorMessage'.</p></td>
</tr>
<tr class="even">
<td><p>saveRequestVariables</p></td>
<td><p>no</p></td>
<td><p>Flag to save request variables.<br />
By default, only response related variables are stored as variables.</p></td>
</tr>
<tr class="odd">
<td><p>saveResponseParameters</p></td>
<td><p>no</p></td>
<td><p>Flag to save all response variables including HTTP status, headers etc.<br />
By default, only the response body is stored as a variable.</p></td>
</tr>
<tr class="even">
<td><p>resultVariablePrefix</p></td>
<td><p>no</p></td>
<td><p>Prefix for the execution variable names.<br />
If prefix is not set, variables will be saved with name as '&lt;taskId&gt;FieldName'.<br />
For example, requestUrl is saved as 'task7RequestUrl' for task with id 'task7'.</p></td>
</tr>
<tr class="odd">
<td><p>saveResponseParametersTransient</p></td>
<td><p>no</p></td>
<td><p>If resolves to true, the response body variable (and response header, status, etc. if set to be stored) will be stored as a transient variable.</p></td>
</tr>
<tr class="even">
<td><p>saveResponseVariableAsJson</p></td>
<td><p>no</p></td>
<td><p>If resolves to true, the response body value will be stored as a JSON variable instead of a String. This is useful if the HTTP service returns JSON and you want to reference the fields using the dot notation (e.g. <em>myResponse.user.name</em>) later on.</p></td>
</tr>
<tr class="odd">
<td><p>parallelInSameTransaction</p></td>
<td><p>-</p></td>
<td><p>If resolves to true, the HTTP call will be done on a different thread and thus making it possible to execute more HTTP tasks in parallel. This is useful when parallel gateways are used and there are multiple HTTP tasks in the parallel flows.</p></td>
</tr>
<tr class="even">
<td><p>httpActivityBehaviorClass</p></td>
<td><p>no</p></td>
<td><p>Full class name of custom extension of org.flowable.engine.impl.bpmn.http.DefaultBpmnHttpActivityDelegate.</p></td>
</tr>
</tbody>
</table>

In addition to the provided fields, following will be set as variables on successful execution, based on 'saveResponseParameters' flag.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Variable</th>
<th>Optional?</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>responseProtocol</p></td>
<td><p>Yes</p></td>
<td><p>Http version</p></td>
</tr>
<tr class="even">
<td><p>responseReason</p></td>
<td><p>Yes</p></td>
<td><p>Http response reason phrase.</p></td>
</tr>
<tr class="odd">
<td><p>responseStatusCode</p></td>
<td><p>Yes</p></td>
<td><p>Http response status code (Example - 200).</p></td>
</tr>
<tr class="even">
<td><p>responseHeaders</p></td>
<td><p>Yes</p></td>
<td><p>Line separated Http response headers.<br />
Example -<br />
Content-Type: application/json<br />
Content-Length: 777</p></td>
</tr>
<tr class="odd">
<td><p>responseBody</p></td>
<td><p>Yes</p></td>
<td><p>Response body as string, if any.</p></td>
</tr>
<tr class="even">
<td><p>errorMessage</p></td>
<td><p>Yes</p></td>
<td><p>Ignored error message, if any.</p></td>
</tr>
</tbody>
</table>

#### Result variables

Remember all the above execution variable names are prefixed by evaluated value of 'resultVariablePrefix'.
For example the response status code can be accessed in another activity as 'task7ResponseStatusCode'.
Here 'task7' is the 'id' of the service task. To override this behavior, set 'resultVariablePrefix' as required.

#### Example usage

The following XML snippet shows an example of using the Http Task.

    <serviceTask id="httpGet" flowable:type="http">
      <extensionElements>
        <flowable:field name="requestMethod" stringValue="GET" />
        <flowable:field name="requestUrl" stringValue="http://flowable.org" />
        <flowable:field name="requestHeaders">
          <flowable:expression>
            <![CDATA[
              Accept: text/html
              Cache-Control: no-cache
            ]]>
          </flowable:expression>
        </flowable:field>
        <flowable:field name="requestTimeout">
          <flowable:expression>
            <![CDATA[
              ${requestTimeout}
            ]]>
          </flowable:expression>
        </flowable:field>
        <flowable:field name="resultVariablePrefix">
          <flowable:string>task7</flowable:string>
        </flowable:field>
      </extensionElements>
    </serviceTask>

#### Error handling

By default Http Task throws a FlowableException when Connection, IO or any unhandled exceptions occur.
By default any redirect/client/server error http status codes are not handled.

The Http task can be configured to handle the exceptions and http status by setting 'failStatusCodes' and/or 'handleStatusCodes' fields. Refer [Http Task configuration](bpmn/ch07b-BPMN-Constructs.md#-http-task-configuration).

The BpmnError thrown by 'handleStatusCodes' should be handled exactly like a normal BPMN exception, by having a corresponding boundary error event.
Below are few examples for exception handling and retry for http task.

##### Fail on '400' and 5XX, async http task and retry with failedJobRetryTimeCycle

    <serviceTask id="failGet" name="Fail test" flowable:async="true" flowable:type="http">
      <extensionElements>
        <flowable:field name="requestMethod">
          <flowable:string><![CDATA[GET]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestUrl">
          <flowable:string><![CDATA[http://localhost:9798/api/fail]]></flowable:string>
        </flowable:field>
        <flowable:field name="failStatusCodes">
          <flowable:string><![CDATA[400, 5XX]]></flowable:string>
        </flowable:field>
        <flowable:failedJobRetryTimeCycle>R3/PT5S</flowable:failedJobRetryTimeCycle>
      </extensionElements>
    </serviceTask>

##### Handle '400' as BmpnError

    <serviceTask id="handleGet" name="HTTP Task" flowable:type="http">
      <extensionElements>
        <flowable:field name="requestMethod">
          <flowable:string><![CDATA[GET]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestUrl">
          <flowable:string><![CDATA[http://localhost:9798/api/fail]]></flowable:string>
        </flowable:field>
        <flowable:field name="handleStatusCodes">
          <flowable:string><![CDATA[4XX]]></flowable:string>
        </flowable:field>
      </extensionElements>
    </serviceTask>
    <boundaryEvent id="catch400" attachedToRef="handleGet">
      <errorEventDefinition errorRef="HTTP400"></errorEventDefinition>
    </boundaryEvent>

##### Ignore exceptions.

    <serviceTask id="ignoreTask" name="Fail test" flowable:type="http">
      <extensionElements>
        <flowable:field name="requestMethod">
          <flowable:string><![CDATA[GET]]></flowable:string>
        </flowable:field>
        <flowable:field name="requestUrl">
          <flowable:string><![CDATA[http://nohost:9798/api]]></flowable:string>
        </flowable:field>
        <flowable:field name="ignoreException">
          <flowable:string><![CDATA[true]]></flowable:string>
        </flowable:field>
      </extensionElements>
    </serviceTask>

##### Exception mapping

Refer [Exception mapping](bpmn/ch07b-BPMN-Constructs.md#exception-mapping)

### Camel Task

The Camel task allows you to send messages to and receive messages from Camel, and thereby enhances the integration features of Flowable. Note that the Camel task is **not** an 'official' task of the BPMN 2.0 spec (and doesn’t have a dedicated icon as a consequence). Hence, in Flowable the Camel task is implemented as a dedicated service task. Also note that you must include the Flowable Camel module in your project to use the Camel task functionality.

#### Defining a Camel Task

The Camel task is implemented as a dedicated [Service Task](bpmn/ch07b-BPMN-Constructs.md#java-service-task) and is defined by setting *'camel'* for the *type* of the service task.

    <serviceTask id="sendCamel" flowable:type="camel">

The process definition itself needs nothing other than the camel type definition on a service task. The integration logic is all delegated to the Camel container. By default, the Flowable engine looks for a camelContext bean in the Spring container. The camelContext bean defines the Camel routes that will be loaded by the Camel container. In the following example, the routes are loaded from a specific Java package, but you can also define routes directly in the Spring configuration itself.

    <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
      <packageScan>
        <package>org.flowable.camel.route</package>
      </packageScan>
    </camelContext>

For more documentation about Camel routes you can look on the [Camel website](http://camel.apache.org/). The basic concepts are demonstrated through a few small samples below. In the first sample, we will do the simplest form of Camel call from a Flowable workflow. Let’s call it SimpleCamelCall.

If you want to define multiple Camel context beans or want to use a different bean name, this can be overridden in the Camel task definition like this:

    <serviceTask id="serviceTask1" flowable:type="camel">
      <extensionElements>
        <flowable:field name="camelContext" stringValue="customCamelContext" />
      </extensionElements>
    </serviceTask>

#### Simple Camel Call example

All the files related to this example can be found in the org.flowable.camel.examples.simpleCamelCall package of flowable-camel module. The target simply activates a specific Camel route. First of all, we need a Spring context that contains the introduction to the routes as mentioned previously. The following serves this purpose:

    <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
      <packageScan>
        <package>org.flowable.camel.examples.simpleCamelCall</package>
      </packageScan>
    </camelContext>

    public class SimpleCamelCallRoute extends RouteBuilder {

      @Override
      public void configure() throws Exception {
        from("flowable:SimpleCamelCallProcess:simpleCall").to("log:org.flowable.camel.examples.SimpleCamelCall");
      }
    }

The route just logs the message body and nothing more. Notice the format of the from endpoint. It consists of three parts:

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Endpoint URL Part</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>flowable</p></td>
<td><p>refers to the engine endpoint</p></td>
</tr>
<tr class="even">
<td><p>SimpleCamelCallProcess</p></td>
<td><p>name of the process</p></td>
</tr>
<tr class="odd">
<td><p>simpleCall</p></td>
<td><p>name of the Camel service in the process</p></td>
</tr>
</tbody>
</table>

OK, our route is now properly configured and accessible to Camel. Now comes the workflow part. The workflow looks like:

    <process id="SimpleCamelCallProcess">
      <startEvent id="start"/>
      <sequenceFlow id="flow1" sourceRef="start" targetRef="simpleCall"/>

      <serviceTask id="simpleCall" flowable:type="camel"/>

      <sequenceFlow id="flow2" sourceRef="simpleCall" targetRef="end"/>
      <endEvent id="end"/>
    </process>

#### Ping Pong example

Our example worked, but nothing is really transferred between Camel and Flowable so there is not much merit in it. In this example, we try to send and receive data to and from Camel. We send a string, Camel concatenates something to it and returns back the result. The sender part is trivial, we send our message in the form of a variable to Camel Task. Here is our caller code:

    @Deployment
    public void testPingPong() {
      Map<String, Object> variables = new HashMap<String, Object>();

      variables.put("input", "Hello");
      Map<String, String> outputMap = new HashMap<String, String>();
      variables.put("outputMap", outputMap);

      runtimeService.startProcessInstanceByKey("PingPongProcess", variables);
      assertEquals(1, outputMap.size());
      assertNotNull(outputMap.get("outputValue"));
      assertEquals("Hello World", outputMap.get("outputValue"));
    }

The variable "input" is actually the input for the Camel route, and outputMap is there to capture the result back from Camel. The process could be something like this:

    <process id="PingPongProcess">
      <startEvent id="start"/>
      <sequenceFlow id="flow1" sourceRef="start" targetRef="ping"/>
      <serviceTask id="ping" flowable:type="camel"/>
      <sequenceFlow id="flow2" sourceRef="ping" targetRef="saveOutput"/>
      <serviceTask id="saveOutput" flowable:class="org.flowable.camel.examples.pingPong.SaveOutput" />
      <sequenceFlow id="flow3" sourceRef="saveOutput" targetRef="end"/>
      <endEvent id="end"/>
    </process>

Note that SaveOutput Service task stores the value of "Output" variable from the context to the previously mentioned OutputMap. Now we have to know how the variables are sent to Camel and returned back. Here comes the notion of Camel behavior into play. The way variables are communicated to Camel is configurable via CamelBehavior. Here we use the default one in our sample, a short description of the other ones comes afterwards. With similar code you can configure the desired Camel behavior:

    <serviceTask id="serviceTask1" flowable:type="camel">
      <extensionElements>
        <flowable:field name="camelBehaviorClass" stringValue="org.flowable.camel.impl.CamelBehaviorCamelBodyImpl" />
      </extensionElements>
    </serviceTask>

If you do not give a specific behavior, then org.flowable.camel.impl.CamelBehaviorDefaultImpl will be set. This behavior copies the variables to Camel properties of the same name. In return, regardless of selected behavior, if the Camel message body is a map, then each of its elements is copied as a variable, else the whole object is copied into a specific variable with the name of "camelBody". Knowing this, this Camel route concludes our second example:

    @Override
    public void configure() throws Exception {
      from("flowable:PingPongProcess:ping").transform().simple("${exchangeProperty.input} World");
    }

In this route, the string "world" is concatenated to the end of the property named "input" and the result will be set in the message body. It’s accessible by checking the "camelBody" variable in the Java service task and copied to "outputMap". Now that the example with its default behavior works, let’s see what the other possibilities are. In starting every Camel route, the Process Instance ID will be copied into a Camel property with the specific name of "PROCESS\_ID\_PROPERTY". It’s later used for correlating the process instance and Camel route. Also, it can be exploited in the Camel route.

There are three different behaviors already available out of the box in Flowable. The behavior can be overwritten by a specific phrase in the route URL. Here’s an example of overriding the already defined behavior in the URL:

    from("flowable:asyncCamelProcess:serviceTaskAsync2?copyVariablesToProperties=true").

The following table provides an overview of three available Camel behaviors:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Behavior</th>
<th>In URL</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>CamelBehaviorDefaultImpl</p></td>
<td><p>copyVariablesToProperties</p></td>
<td><p>Copy Flowable variables as Camel properties</p></td>
</tr>
<tr class="even">
<td><p>CamelBehaviorCamelBodyImpl</p></td>
<td><p>copyCamelBodyToBody</p></td>
<td><p>Copy only the Flowable variable named "camelBody" as the Camel message body</p></td>
</tr>
<tr class="odd">
<td><p>CamelBehaviorBodyAsMapImpl</p></td>
<td><p>copyVariablesToBodyAsMap</p></td>
<td><p>Copy all the Flowable variables in a map as the Camel message body</p></td>
</tr>
</tbody>
</table>

The above table describes how Flowable variables are going to be transferred to Camel. The following table describes how the Camel variables are returned back to Flowable. This can only be configured in route URLs.

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>URL</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>Default</p></td>
<td><p>If Camel body is a map, copy each element as a Flowable variable, otherwise copy the whole Camel body as a "camelBody" Flowable variable</p></td>
</tr>
<tr class="even">
<td><p>copyVariablesFromProperties</p></td>
<td><p>Copy Camel properties as Flowable variables of the same name</p></td>
</tr>
<tr class="odd">
<td><p>copyCamelBodyToBodyAsString</p></td>
<td><p>As for default, but if camelBody is not a map, first convert it to String and then copy it into "camelBody"</p></td>
</tr>
<tr class="even">
<td><p>copyVariablesFromHeader</p></td>
<td><p>Additionally copy Camel headers to Flowable variables of the same names</p></td>
</tr>
</tbody>
</table>

#### Returning back the variables

What is mentioned above about passing variables only holds for the initiating side of the variable transfer, whether you’re coming from from Camel to Flowable or from Flowable to Camel.  
It is important to note that because of the special non-blocking behavior of Flowable, variables are not automatically returned back from Flowable to Camel.
For that to happen, a special syntax is available. There can be one or more parameters in a Camel route URL with the format of var.return.someVariableName.
All variables having a name equal to one of these parameters (without var.return part) will be considered as output variables and will be copied back as Camel properties with the same names.  
For example in a route like:

    from("direct:start").to("flowable:process?var.return.exampleVar").to("mock:result");

A Flowable variable with the name of exampleVar will be considered as an output variable and will be copied back as a property in Camel with the same name.

#### Asynchronous Ping Pong example

All the previous examples were synchronous. The process instance waits until the Camel route is concluded and returned. In some cases, we might need the Flowable process instance to continue. For such purposes, the asynchronous capability of the Camel service task is useful. You can make use of this feature by setting the *async* property of the Camel service task to true.

    <serviceTask id="serviceAsyncPing" flowable:type="camel" flowable:async="true"/>

By setting this feature, the specified Camel route is activated asynchronously by the Flowable job executor. When you define a queue in the Camel route, the Flowable process instance will continue with the activities defined after the Camel service task in the process definition. The Camel route will be executed fully asynchronously from the process execution. If you want to wait for a response of the Camel service task somewhere in your process definition, you can use a receive task.

    <receiveTask id="receiveAsyncPing" name="Wait State" />

The process instance will wait until a signal is received, for example from Camel. In Camel you can send a signal to the process instance by sending a message to the proper Flowable endpoint.

     from("flowable:asyncPingProcess:serviceAsyncPing").to("flowable:asyncPingProcess:receiveAsyncPing");

-   constant string "flowable"

-   process name

-   receive task name

#### Instantiate workflow from Camel route

In all the previous examples, the Flowable process instance is started first and the Camel route was started from the process instance. It is also possible to do things the other way around, with a process instance being started or invoked from an already started Camel route. It’s very similar to signalling a receive task. Here’s a sample route:

    from("direct:start").to("flowable:camelProcess");

As you can see, the URL has two parts: the first is the constant string "flowable" and the second is the name of the process definition. Obviously, the process definition should already be deployed to the Flowable engine.

It is also possible to set the initiator of the process instance to some authenticated user ID that is provided in a Camel header. To achieve this, first of all, an initiator variable must be specified in the process definition:

    <startEvent id="start" flowable:initiator="initiator" />

Then given that the user ID is contained in a Camel header named *CamelProcessInitiatorHeader*, the Camel route could be defined as follows:

    from("direct:startWithInitiatorHeader")
        .setHeader("CamelProcessInitiatorHeader", constant("kermit"))
        .to("flowable:InitiatorCamelCallProcess?processInitiatorHeaderName=CamelProcessInitiatorHeader");

### Manual Task

#### Description

A *Manual Task* defines a task that is external to the BPM engine. It’s used to model work that is done by somebody, which the engine does not need to know of, nor is there a system or user interface. For the engine, a manual task is handled as a **pass-through activity**, automatically continuing the process from the moment process execution arrives into it.

#### Graphical Notation

A manual task is visualized as a rounded rectangle, with a little 'hand' icon in the upper left corner



#### XML representation

    <manualTask id="myManualTask" name="Call client for more information" />

### Java Receive Task

#### Description

A Receive Task is a simple task that waits for the arrival of a certain message. Currently, we have only implemented Java semantics for this task. When process execution arrives at a Receive Task, the process state is committed to the persistence store. 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 past the Receive Task.

#### Graphical notation

A Receive Task is visualized as a task (rounded rectangle) with a message icon in the top left corner. The message is white (a black message icon would have send semantics)



#### XML representation

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

To continue a process instance that is currently waiting at such a Receive Task, the *runtimeService.trigger(executionId)* must be called using the ID of the execution that arrived in the Receive Task. 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();
    assertNotNull(execution);

    runtimeService.trigger(execution.getId());

### Shell Task

#### Description

The Shell task allows you to run shell scripts and commands. Note that the Shell task is **not** an 'official' task of BPMN 2.0 spec (and doesn’t have a dedicated icon as a consequence).

#### Defining a Shell task

The Shell task is implemented as a dedicated [Service Task](bpmn/ch07b-BPMN-Constructs.md#java-service-task) and is defined by setting *'shell'* for the *type* of the service task.

    <serviceTask id="shellEcho" flowable:type="shell">

The Shell task is configured by [field injection](bpmn/ch07b-BPMN-Constructs.md#field-injection). All the values for these properties can contain EL expression, which are resolved at runtime during process execution. The following properties can be set:

<table>
<colgroup>
<col style="width: 20%" />
<col style="width: 20%" />
<col style="width: 20%" />
<col style="width: 20%" />
<col style="width: 20%" />
</colgroup>
<thead>
<tr class="header">
<th>Property</th>
<th>Required?</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>command</p></td>
<td><p>yes</p></td>
<td><p>String</p></td>
<td><p>Shell command to execute.</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>arg1-5</p></td>
<td><p>no</p></td>
<td><p>String</p></td>
<td><p>Parameter 1 to Parameter 5</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>wait</p></td>
<td><p>no</p></td>
<td><p>true/false</p></td>
<td><p>Wait if necessary, until the shell process has terminated.</p></td>
<td><p>true</p></td>
</tr>
<tr class="even">
<td><p>redirectError</p></td>
<td><p>no</p></td>
<td><p>true/false</p></td>
<td><p>Merge standard error with the standard output.</p></td>
<td><p>false</p></td>
</tr>
<tr class="odd">
<td><p>cleanEnv</p></td>
<td><p>no</p></td>
<td><p>true/false</p></td>
<td><p>Shell process does not inherit current environment.</p></td>
<td><p>false</p></td>
</tr>
<tr class="even">
<td><p>outputVariable</p></td>
<td><p>no</p></td>
<td><p>String</p></td>
<td><p>Name of variable to hold the output</p></td>
<td><p>Output is not recorded.</p></td>
</tr>
<tr class="odd">
<td><p>errorCodeVariable</p></td>
<td><p>no</p></td>
<td><p>String</p></td>
<td><p>Name of variable to hold any result error code</p></td>
<td><p>Error level is not registered.</p></td>
</tr>
<tr class="even">
<td><p>directory</p></td>
<td><p>no</p></td>
<td><p>String</p></td>
<td><p>Default directory of the shell process</p></td>
<td><p>Current directory</p></td>
</tr>
</tbody>
</table>

#### Example usage

The following XML snippet shows an example of using the Shell Task. It runs the shell script "cmd /c echo EchoTest", waits for it to be terminated and puts the result in *resultVar*:

    <serviceTask id="shellEcho" flowable:type="shell" >
      <extensionElements>
        <flowable:field name="command" stringValue="cmd" />
        <flowable:field name="arg1" stringValue="/c" />
        <flowable:field name="arg2" stringValue="echo" />
        <flowable:field name="arg3" stringValue="EchoTest" />
        <flowable:field name="wait" stringValue="true" />
        <flowable:field name="outputVariable" stringValue="resultVar" />
      </extensionElements>
    </serviceTask>

### External Worker Task

#### Description

The External Worker Task allows you to create jobs that should be acquired and executed by External Workers.
An External Worker can acquire jobs over the Java API or REST API.
This is similar to an async Service Task.
The difference is that instead of Flowable executing the logic,
an External Worker, which can be implemented in any language, queries Flowable for jobs, executes them and sends the result to Flowable.
Note that the External Worker task is **not** an 'official' task of BPMN 2.0 spec (and doesn’t have a dedicated icon as a consequence).

#### Defining an External Worker Task

The External Worker task is implemented as a dedicated [Service Task](bpmn/ch07b-BPMN-Constructs.md#java-service-task) and is defined by setting *'external-worker'* for the *type* of the service task.

```xml
<serviceTask id="externalWorkerOrder" flowable:type="external-worker">
```

The External Worker task is configured by setting the `topic` (can be an EL expression) which the External Worker uses to query for jobs to execute.

#### Example usage

The following XML snippet shows an example of using the External Worker Task.
The External Worker is a wait state.
When the execution reaches the task it will create an External Worker Job, which can be acquired by an External Worker.
Once the External Worker is done with the job and notifies Flowable of the completion the execution of the process will continue.


```xml
<serviceTask id="externalWorkerOrder" flowable:type="external-worker" flowable:topic="orderService" />
```

#### Acquiring External Worker Job

External Worker Jobs are acquired via the `ManagementService#createExternalWorkerJobAcquireBuilder` by using a `ExternalWorkerJobAcquireBuilder`

```java
List<AcquiredExternalWorkerJob> acquiredJobs = managementService.createExternalWorkerJobAcquireBuilder()
                .topic("orderService", Duration.ofMinutes(30))
                .acquireAndLock(5, "orderWorker-1");
```

By using the above Java snippet External Worker jobs can be acquired.
With the snippet we did the following:

* Query for External Worker Jobs with the topic *orderService*.
* Acquire and lock the jobs for 30 minutes waiting for the completion signal from the External Worker.
* Acquire maximum of 5 jobs
* The owner of the jobs is the worker with id *orderWorker-1*

An `AcquiredExternalWorkerJob` also has access to the Process variables.
When the External Worker Task is exclusive, acquiring the job will lock the Process Instance.

#### Completing an External Worker Job

External Worker Jobs are completed via the `ManagementService#createExternalWorkerCompletionBuilder(String, String)` by using an `ExternalWorkerCompletionBuilder`

```java
managementService.createExternalWorkerCompletionBuilder(acquiredJob.getId(), "orderWorker-1")
                .variable("orderStatus", "COMPLETED")
                .complete();
```

A Job can be completed only by the worker that acquired it. Otherwise a `FlowableIllegalArgumentException` will be thrown.

Using the snippet above the task is completed and the process execution will continue.
The continuation of the execution is done asynchronously in a new transaction.
This means that completing an external worker task will only create an asynchronous (new) job to execute the completion (and the current thread returns after doing that).
Any steps in the model that follow after the external worker task will be executed in that transaction, similar to a regular async service task.


#### Error handling for an External Worker Job

There are 2 ways of handling errors for an external worker job:

* Business error via `ManagementService#createExternalWorkerCompletionBuilder(String, String)` by using an `ExternalWorkerCompletionBuilder`


```java
managementService.createExternalWorkerCompletionBuilder(acquiredJob.getId(), "orderWorker-1")
                .variable("orderStatus", "FAILED")
                .bpmnError("orderFailed");
```

With this snippet the *orderStatus* variable will be set on the process and a BPMN Error with the code *orderFailed* will be thrown.
A BPMN Error can only be thrown by the worker that acquired the job.

* Technical error via `ManagementService#createExternalWorkerJobFailureBuilder(String, String)` by using an `ExternalWorkerJobFailureBuilder`


```java
managementService.createExternalWorkerJobFailureBuilder(acquiredJob.getId(), "orderWorker-1")
                .errorMessage("Failed to run job. Database not accessible")
                .errorDetails("Some complex and long error details")
                .retries(4)
                .retryTimeout(Duration.ofHours(1))
                .fail();
```

With this snippet the following will be done:

* The error message and error details will be set on the job
* The retry count for the job will be set to 4
* The job will be available for acquiring after 1 hour

The Job can only be failed by the worker that acquired it.
If no retries have been set, flowable will automatically decrease the number of retries for a job by 1.
When the number of retries is 0 the job will be moved to the DeadLetter table job and will no longer be available for acquiring.

#### Querying External Worker Jobs

External Worker Jobs are queried by using the `ExternalWorkerJobQuery` by creating it via `ManagementService#createExternalWorkerJobQuery`.


### Execution listener

Execution listeners allow you to execute external Java code or evaluate an expression when certain events occur during process execution. The events that can be captured are:

-   Starting and ending a process instance.

-   Taking a transition.

-   Starting and ending an activity.

-   Starting and ending a gateway.

-   Starting and ending an intermediate event.

-   Ending a start event and starting an end event.

The following process definition contains 3 execution listeners:

    <process id="executionListenersProcess">

      <extensionElements>
        <flowable:executionListener
          class="org.flowable.examples.bpmn.executionlistener.ExampleExecutionListenerOne"
          event="start" />
      </extensionElements>

      <startEvent id="theStart" />
      <sequenceFlow sourceRef="theStart" targetRef="firstTask" />

      <userTask id="firstTask" />
      <sequenceFlow sourceRef="firstTask" targetRef="secondTask">
        <extensionElements>
          <flowable:executionListener
            class="org.flowable.examples.bpmn.executionListener.ExampleExecutionListenerTwo" />
        </extensionElements>
      </sequenceFlow>

      <userTask id="secondTask" >
        <extensionElements>
          <flowable:executionListener
            expression="${myPojo.myMethod(execution.event)}"
            event="end" />
        </extensionElements>
      </userTask>
      <sequenceFlow sourceRef="secondTask" targetRef="thirdTask" />

      <userTask id="thirdTask" />
      <sequenceFlow sourceRef="thirdTask" targetRef="theEnd" />

      <endEvent id="theEnd" />

    </process>

The first execution listener is notified when the process starts. The listener is an external Java-class (ExampleExecutionListenerOne) and should implement an org.flowable.engine.delegate.ExecutionListener interface. When the event occurs (in this case end event), the method notify(ExecutionListenerExecution execution) is called.

    public class ExampleExecutionListenerOne implements ExecutionListener {

      public void notify(ExecutionListenerExecution execution) throws Exception {
        execution.setVariable("variableSetInExecutionListener", "firstValue");
        execution.setVariable("eventReceived", execution.getEventName());
      }
    }

It is also possible to use a delegation class that implements the org.flowable.engine.delegate.JavaDelegate interface. These delegation classes can then be reused in other constructs, such as a delegation for a serviceTask.

The second execution listener is called when the transition is taken. Note that the listener element doesn’t define an event, since only take events are fired on transitions. **Values in the event attribute are ignored when a listener is defined on a transition.**

The last execution listener is called when the activity secondTask ends. Instead of using the class on the listener declaration, a expression is defined instead, which is evaluated/invoked when the event is fired.

    <flowable:executionListener expression="${myPojo.myMethod(execution.eventName)}" event="end" />

As with other expressions, execution variables are resolved and can be used. Because the execution implementation object has a property that exposes the event name, it’s possible to pass the event-name to your methods using execution.eventName.

Execution listeners also support using a delegateExpression, [similar to a service task](bpmn/ch07b-BPMN-Constructs.md#xml-representation).

    <flowable:executionListener event="start" delegateExpression="${myExecutionListenerBean}" />

A while back, we also introduced a new type of execution listener, the org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener. This script execution listener allows you to execute a piece of script logic for an execution listener event.

    <flowable:executionListener event="start"
        class="org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener">
      <flowable:field name="script">
        <flowable:string>
          def bar = "BAR";  // local variable
          foo = "FOO"; // pushes variable to execution context
          execution.setVariable("var1", "test"); // test access to execution instance
          bar // implicit return value
        </flowable:string>
      </flowable:field>
      <flowable:field name="language" stringValue="groovy" />
      <flowable:field name="resultVariable" stringValue="myVar" />

    </flowable:executionListener>

Scriptable execution listeners became a first-class citizen using a more compact syntax, avoiding
to hard-code the class name:

    <flowable:executionListener event="start" type="script">
      <flowable:script language="groovy">
        <![CDATA[
          def bar = "BAR";  // local variable
          execution.setVariable("var1", "test"); // test access to execution instance
        ]]>
        </flowable:script>
    </flowable:executionListener>

#### Field injection on execution listeners

When using an execution listener that is configured with the class attribute, field injection can be applied. This is exactly the same mechanism as used in [Service task field injection](bpmn/ch07b-BPMN-Constructs.md#field-injection), which contains an overview of the possibilities provided by field injection.

The fragment below shows a simple example process with an execution listener with fields injected.

    <process id="executionListenersProcess">
      <extensionElements>
        <flowable:executionListener
            class="org.flowable.examples.bpmn.executionListener.ExampleFieldInjectedExecutionListener"
            event="start">

          <flowable:field name="fixedValue" stringValue="Yes, I am " />
          <flowable:field name="dynamicValue" expression="${myVar}" />

        </flowable:executionListener>
      </extensionElements>

      <startEvent id="theStart" />
      <sequenceFlow sourceRef="theStart" targetRef="firstTask" />

      <userTask id="firstTask" />
      <sequenceFlow sourceRef="firstTask" targetRef="theEnd" />

      <endEvent id="theEnd" />
    </process>

    public class ExampleFieldInjectedExecutionListener implements ExecutionListener {

      private Expression fixedValue;

      private Expression dynamicValue;

      public void notify(ExecutionListenerExecution execution) throws Exception {
        execution.setVariable("var", fixedValue.getValue(execution).toString() +
            dynamicValue.getValue(execution).toString());
      }
    }

The class ExampleFieldInjectedExecutionListener concatenates the two injected fields (one fixed an the other dynamic) and stores this in the process variable 'var'.

    @Deployment(resources = {
      "org/flowable/examples/bpmn/executionListener/ExecutionListenersFieldInjectionProcess.bpmn20.xml"})
    public void testExecutionListenerFieldInjection() {
      Map<String, Object> variables = new HashMap<String, Object>();
      variables.put("myVar", "listening!");

      ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
          "executionListenersProcess", variables);

      Object varSetByListener = runtimeService.getVariable(processInstance.getId(), "var");
      assertNotNull(varSetByListener);
      assertTrue(varSetByListener instanceof String);

      // Result is a concatenation of fixed injected field and injected expression
      assertEquals("Yes, I am listening!", varSetByListener);
    }

Note that the same rules with regards to thread-safety apply to service tasks. Please read the [relevant section](bpmn/ch07b-BPMN-Constructs.md#field-injection-and-thread-safety) for more information.

#### Throwing BPMN Error in Execution Listeners
It is possible to throw BPMN Errors out of execution listener code, which is caught by a matching [error boundary event](bpmn/ch07b-BPMN-Constructs.md#error-boundary-event) or [error start event](bpmn/ch07b-BPMN-Constructs.md#error-start-event) in the model. 
This can be done using the Flowable `org.flowable.engine.delegate.BpmnError` class. See section [throwing BPMN Errors](bpmn/ch07b-BPMN-Constructs.md#throwing-bpmn-errors) for
examples and further description.

It is important to note, that BPMN Errors thrown in Execution Listeners are only caught on _parent scoped_ error boundary events, not on the boundary event of the activity.

The following image illustrates that: 


Given that _A Task_ has an execution listener defined, which throws a BpmnError at some point: 
The error is only caught if the error boundary event on the _Subprocess_ matches (the red one in the image). 
The error boundary event on the _A Task_ is ignored in this case.
This is a recommended practice anyway.

The reason for this is: When execution listeners are called, the activity is either not yet fully initialized (for _start_ listeners) or the scope was already destroyed (for _end_ listeners).

### Task listener

A *task listener* is used to execute custom Java logic or an expression on the occurrence of a certain task-related event.

A task listener can only be added in the process definition as a child element of a [user task](bpmn/ch07b-BPMN-Constructs.md#user-task). Note that this also must happen as a child of the *BPMN 2.0 extensionElements* and in the *flowable* namespace, since a task listener is a Flowable-specific construct.

    <userTask id="myTask" name="My Task" >
      <extensionElements>
        <flowable:taskListener event="create" class="org.flowable.MyTaskCreateListener" />
      </extensionElements>
    </userTask>

A *task listener* supports the following attributes:

-   **event** (required): the type of task event on which the task listener will be invoked. Possible events are

    -   **create**: occurs when the task has been created and **all task properties are set**.

    -   **assignment**: occurs when the task is assigned to somebody. Note: when process execution arrives in a userTask, first an *assignment* event will be fired, **before** the *create* event is fired. This might seem an unnatural order, but the reason is pragmatic: when receiving the *create* event, we usually want to inspect all properties of the task including the assignee.

    -   **complete**: occurs when the task is completed and just before the task is deleted from the runtime data.

    -   **delete**: occurs just before the task is going to be deleted. Notice that it will also be executed when task is normally finished via completeTask.

-   **class**: the delegation class that must be called. This class must implement the org.flowable.task.service.delegate.TaskListener interface.



    public class MyTaskCreateListener implements TaskListener {

      public void notify(DelegateTask delegateTask) {
        // Custom logic goes here
      }
    }

It is also possible to use [field injection](bpmn/ch07b-BPMN-Constructs.md#field-injection) to pass process variables or the execution to the delegation class. Note that an instance of the delegation class is created on process deployment (as is the case with any class delegation in Flowable), which means that the instance is shared between all process instance executions.

-   **expression**: (cannot be used together with the *class* attribute): specifies an expression that will be executed when the event happens. It is possible to pass the DelegateTask object and the name of the event (using task.eventName) as parameter to the called object.



    <flowable:taskListener event="create" expression="${myObject.callMethod(task, task.eventName)}" />

-   **delegateExpression** allows you to specify an expression that resolves to an object implementing the TaskListener interface, [similar to a service task](bpmn/ch07b-BPMN-Constructs.md#xml-representation).



    <flowable:taskListener event="create" delegateExpression="${myTaskListenerBean}" />

-   A while back, we also introduced a new type of task listener, the org.flowable.engine.impl.bpmn.listener.ScriptTaskListener. This script task listener allows you to execute a piece of script logic for a task listener event.



    <flowable:taskListener event="complete" class="org.flowable.engine.impl.bpmn.listener.ScriptTaskListener" >
      <flowable:field name="script">
        <flowable:string>
          def bar = "BAR";  // local variable
          foo = "FOO"; // pushes variable to execution context
          task.setOwner("kermit"); // test access to task instance
          bar // implicit return value
        </flowable:string>
      </flowable:field>
      <flowable:field name="language" stringValue="groovy" />
      <flowable:field name="resultVariable" stringValue="myVar" />
    </flowable:taskListener>

- Scriptable task listeners became a first-class citizen using a more compact syntax, avoiding to hard-code the class name:



    <flowable:taskListener event="complete" type="script">
      <flowable:script language="groovy" resultVariable="myVar">
        <![CDATA[
          def bar = "BAR";  // local variable
          task.setOwner("kermit"); // test access to task instance
          bar // implicit return value
        ]]>
      </flowable:script>
    </flowable:taskListener>

#### Throwing BPMN Error in Task Listeners

Jump to section [Throwing BPMN Error in Execution Listeners](bpmn/ch07b-BPMN-Constructs.md#throwing-bpmn-error-in-execution-listeners) as the same rules apply for task listeners.

### Multi-instance (for each)

#### Description

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

A *multi-instance* is a regular activity that has extra properties defined (named *'multi-instance* characteristics'*) that will cause the activity to be executed multiple times at runtime. The following activities can become a \_multi-instance activity:*

-   [User Task](bpmn/ch07b-BPMN-Constructs.md#user-task)

-   [Script Task](bpmn/ch07b-BPMN-Constructs.md#script-Task)

-   [Java Service Task](bpmn/ch07b-BPMN-Constructs.md#java-service-task)

-   [Web Service Task](bpmn/ch07b-BPMN-Constructs.md#web-service-task)

-   [Business Rule Task](bpmn/ch07b-BPMN-Constructs.md#business-rule-task)

-   [Email Task](bpmn/ch07b-BPMN-Constructs.md#email-task)

-   [Manual Task](bpmn/ch07b-BPMN-Constructs.md#manual-task)

-   [Receive Task](bpmn/ch07b-BPMN-Constructs.md#java-receive-task)

-   [(Embedded) Sub-Process](bpmn/ch07b-BPMN-Constructs.md#aocess)

-   [Call Activity](bpmn/ch07b-BPMN-Constructs.md#call-activity-(sub-process))

A [Gateway](bpmn/ch07b-BPMN-Constructs.md#gateways) or [Event](bpmn/ch07b-BPMN-Constructs.md#events) **cannot** become multi-instance.

As required by the BPMN 2.0 specification, 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 (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 (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. The loopCounter variable can be renamed using a Flowable **elementIndexVariable** attribute.

#### Graphical notation

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



#### XML representation

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 in parallel.

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

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

Expressions that resolve to a positive number are also allowed:

    <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 that 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}" flowable:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="false">
        <loopDataInputRef>assigneeList</loopDataInputRef>
        <inputDataItem name="assignee" />
      </multiInstanceLoopCharacteristics>
    </userTask>

Suppose the variable assigneeList contains the values \\\[kermit, gonzo, fozzie\\\]. 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 the names are pretty hard to remember, and due to the BPMN 2.0 schema restrictions, they can’t contain expressions. Flowable solves this by offering the **collection** and **elementVariable** attributes on the multiInstanceCharacteristics:

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

Note that the collection attribute will be resolved as an expression. When the expression resolves to a String instead of a collection, either because it is a static string value or the expression itself resolves to a String, the resulting value will be used as the variable name for fetching the collection process variable.

For example, in the following snippet the collection is assumed to be stored in the assigneeList process variable:

    <userTask id="miTasks" name="My Task" flowable:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="true"
         flowable:collection="assigneeList" flowable:elementVariable="assignee" >
      </multiInstanceLoopCharacteristics>
    </userTask>

For example, assuming the myService.getCollectionVariableName() returns a String value, that value will be used as variable name to fetch the collection stored as a process variable.

    <userTask id="miTasks" name="My Task" flowable:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="true"
         flowable:collection="${myService.getCollectionVariableName()}" flowable: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 an 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" flowable:assignee="${assignee}">
      <multiInstanceLoopCharacteristics isSequential="false"
         flowable:collection="assigneeList" flowable:elementVariable="assignee" >
        <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.6 }</completionCondition>
      </multiInstanceLoopCharacteristics>
    </userTask>

In this example, there will be parallel instances 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.

#### Boundary events and multi-instance

Since a multi-instance is a regular activity, it is possible to define a [boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events) on its boundary. In the case of an interrupting boundary event, when the event is caught, **all instances** that are still active will be destroyed. Take, for example, the following multi-instance sub-process:



Here, all instances of the sub-process will be destroyed when the timer fires, regardless of how many instances there are or which inner activities haven’t yet completed.

#### Multi instance and execution listeners

There is a caveat when using execution listeners in combination with multi instance. Take, for example, the following snippet of BPMN 2.0 XML, which is defined at the same level as the *multiInstanceLoopCharacteristics* XML element is set:

    <extensionElements>
        <flowable:executionListener event="start" class="org.flowable.MyStartListener"/>
        <flowable:executionListener event="end" class="org.flowable.MyEndListener"/>
    </extensionElements>

For a normal BPMN activity, there will be an invocation of these listeners when the activity is started and ended.

However, when the activity is multi-instance, the behavior is different:

-   When the multi-instance activity is entered, before any of the *inner* activities is executed, a start event is thrown. The *loopCounter* variable is not yet set (it is null).

-   For each of the actual activities visited, a start event is thrown. The *loopCounter* variable is set.

The same logic applies for the end event:

-   After leaving the actual activity, an end even is thrown. The *loopCounter* variable is set.

-   When the multi-instance activity has finished as a whole, an end event is thrown. The *loopCounter* variable is not set.

For example:

    <subProcess id="subprocess1" name="Sub Process">
      <extensionElements>
        <flowable:executionListener event="start" class="org.flowable.MyStartListener"/>
        <flowable:executionListener event="end" class="org.flowable.MyEndListener"/>
      </extensionElements>
      <multiInstanceLoopCharacteristics isSequential="false">
        <loopDataInputRef>assignees</loopDataInputRef>
        <inputDataItem name="assignee"></inputDataItem>
      </multiInstanceLoopCharacteristics>
      <startEvent id="startevent2" name="Start"></startEvent>
      <endEvent id="endevent2" name="End"></endEvent>
      <sequenceFlow id="flow3" name="" sourceRef="startevent2" targetRef="endevent2"></sequenceFlow>
    </subProcess>

In this example, suppose the *assignees* list has three items. The following happens at runtime:

-   A start event is thrown for the multi-instance as a whole. The *start* execution listener is invoked. The *loopCounter* and the *assignee* variables will not be set (they will be null).

-   A start event is thrown for each activity instance. The *start* execution listener is invoked three times. The *loopCounter* and the *assignee* variables will be set (not null).

-   So, in total, the start execution listener is invoked four times.

Note that the same applies when the *multiInstanceLoopCharacteristics* are defined on something other than a sub-process too. For example, if the example above was a simple userTask, the same reasoning still applies.

### Compensation Handlers

#### Description

If an activity is used for compensating the effects of another activity, it can be declared to be a *compensation handler*. Compensation handlers do not exist in normal flows and are only executed when a compensation event is thrown.

Compensation handlers must not have incoming or outgoing sequence flows.

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

#### Graphical notation

If an activity is a compensation handler, the compensation event icon is displayed in the center bottom area. The following excerpt from a process diagram shows a service task with an attached compensation boundary event, which is associated to a compensation handler. Notice the compensation handler icon in the bottom canter area of the "cancel hotel reservation" service task.



#### XML representation

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" flowable:class="...">
    </serviceTask>

## Sub-Processes and Call Activities

### Sub-Process

#### Description

A *Sub-Process* is an activity that contains other activities, gateways, events, and so on, which in itself forms a process that is part of the bigger process. A *Sub-Process* is completely defined inside a parent process (that’s why it’s often called an *embedded* Sub-Process).

Sub-Processes have two major use cases:

-   Sub-Processes allow **hierarchical modeling**. Many modeling tools allow Sub-Processes to be *collapsed*, hiding all the details of the Sub-Process, resulting in a high-level, end-to-end overview of the business process.

-   A Sub-Process creates a new **scope for events**. Events that are thrown during execution of the Sub-Process can be caught by [a boundary event](bpmn/ch07b-BPMN-Constructs.md#boundary-events) on the boundary of the Sub-Process, creating a scope for that event limited to the Sub-Process.

Using a Sub-Process does impose some constraints:

-   A Sub-Process can only have **one 'none start event'**, no other start event types are allowed. A Sub-Process must **at least have one 'end event'**. Note that the BPMN 2.0 specification allows the omission of the start and end events in a Sub-Process, but the current Flowable implementation does not support this.

-   **Sequence flows cannot cross Sub-Process boundaries.**

#### Graphical Notation

A Sub-Process is visualized as a typical activity (a rounded rectangle). If the Sub-Process is *collapsed*, only the name and a plus-sign are displayed, giving a high-level overview of the process:



If the Sub-Process is *expanded*, the steps of the Sub-Process are displayed within the Sub-Process boundaries:



One of the main reasons to use a Sub-Process is to define a scope for a certain event. The following process model shows this: both the *investigate software/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 (in which activities must be done in time) is constrained by the Sub-Process.



#### XML representation

A Sub-Process is defined by the *subProcess* element. All activities, gateways, events, and son on, that are part of the Sub-Process, need to be enclosed within this element.

    <subProcess id="subProcess">

      <startEvent id="subProcessStart" />

      ... other Sub-Process elements ...

      <endEvent id="subProcessEnd" />

     </subProcess>

### Event Sub-Process

#### Description

The Event Sub-Process is new in BPMN 2.0. An Event Sub-Process is a sub-process that is triggered by an event. An Event Sub-Process can be added at the process level or at any sub-process level. The event used to trigger an event sub-process is configured using a start event. From this, it follows that 'none start events' are not supported for Event Sub-Processes. An Event Sub-Process might be triggered using events, such as 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 sub-process) hosting the Event Sub-Process is created. The subscription is removed when the scope is destroyed.

An Event Sub-Process may be interrupting or non-interrupting. An interrupting sub-process cancels any executions in the current scope. A non-interrupting Event Sub-Process spawns a new concurrent execution. While an interrupting Event Sub-Process can only be triggered once for each activation of the scope hosting it, a non-interrupting Event Sub-Process can be triggered multiple times. The fact of whether a sub-process is interrupting is configured using the start event triggering the Event Sub-Process.

An Event Sub-Process must not have any incoming or outgoing sequence flows. As an Event Sub-Process is triggered by an event, an incoming sequence flow makes no sense. When an Event Sub-Process is ended, either the current scope is ended (if an interrupting Event Sub-Process), or the concurrent execution spawned for the non-interrupting sub-process is ended.

**Current limitations:**

-   Flowable supports Event Sub-Process triggered using an Error, Timer, Signal and Message Start Events.

#### Graphical Notation

An Event Sub-Process can be visualized as an [embedded sub-process](bpmn/ch07b-BPMN-Constructs.md#graphical-notation) with a dotted outline.



#### XML representation

An Event Sub-Process is represented using XML in the same way as an embedded sub-process. In addition the attribute triggeredByEvent must have the value true:

    <subProcess id="eventSubProcess" triggeredByEvent="true">
        ...
    </subProcess>

#### Example

The following is an example of an Event Sub-Process triggered using an Error Start Event. The Event Sub-Process is located at the "process level", in other words, is scoped to the process instance:



This is how the Event Sub-Process would look 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 Sub-Process can also be added to an embedded sub-process. If it’s added to an embedded sub-process, it becomes an alternative to a boundary event. Consider the two following process diagrams. In both cases the embedded sub-process 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 alternatives:

-   The embedded sub-process is executed using the same execution that executed the scope it is hosted in. This means that an embedded sub-process has access to the variables local to its scope. When using a boundary event, the execution created for executing the embedded sub-process is deleted by the sequence flow leaving the boundary event. This means that the variables created by the embedded sub-process are not available anymore.

-   When using an Event Sub-Process, the event is completely handled by the sub-process 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 sub-process is better suited for solving a particular process modeling or implementation problem.

### Transaction sub-process

#### Description

A transaction sub-process is an embedded sub-process that can be used to group multiple activities to a transaction. A transaction is a logical unit of work that allows to group a set of individual activities, such that they either succeed or fail collectively.

**Possible outcomes of a transaction:** A transaction can have three different outcomes:

-   A transaction is *successful* if it isn’t either cancelled or terminated by a hazard. If a transaction sub-process is successful, it is left using the outgoing sequence flows. A successful transaction might be compensated if a compensation event is thrown later in the process. *Note:* just as with "ordinary" embedded sub-processes, a transaction may be compensated after successful completion using an intermediary throwing compensation event.

-   A transaction is *canceled* if an execution reaches the cancel end event. In this case, all executions are terminated and removed. A single remaining execution is then set to the cancel boundary event, which triggers compensation. After compensation has completed, the transaction sub-process is left using the outgoing sequence flows of the cancel boundary event.

-   A transaction is ended by a *hazard* if an error event is thrown that is not caught within the scope of the transaction sub-process. This also applies if the error is caught on the boundary of the transaction sub-process. In these cases, compensation is not performed.

The following diagram illustrates the three different outcomes:



**Relation to ACID transactions:** it is important not to confuse the BPMN transaction sub-process with technical (ACID) transactions. The BPMN transaction sub-process is not a way to scope technical transactions. In order to understand transaction management in Flowable, read the section on [concurrency and transactions](bpmn/ch07b-BPMN-Constructs.md#transactions-and-concurrency). A BPMN transaction is different 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 the case where one of the activities grouped by a transaction is a user task: 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.

-   As a BPMN transaction spans multiple ACID transactions, we loose ACID properties. For example, 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 intermediary 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 thus also have an intermediary 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 loose 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 intermediary inconsistencies are only present for very short periods of times).

-   A BPMN business transaction can 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 this point, they cannot be rolled back anymore.

As 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 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. As this might be undesirable from a business perspective, a booking service might choose to allow for a certain amount of overbooking.

-   In addition, as the transaction can be aborted in the 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 this 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 by 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, for instance, that a transaction is cancelled if a cancel event occurs in the underlying protocol. As an embeddable engine, Flowable does not currently 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 Flowable, the consistency model for BPMN transactions is superposed on top of the consistency model for process execution. Flowable executes processes in a transactional way. Concurrency is addressed using optimistic locking. In Flowable, 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. Or, the effects of a compensation handler cannot be committed if some other participant in the underlying ACID transaction sets the transaction to the state rollback-only. Or, 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 Flowable, the same set of rules apply as when implementing "ordinary" processes and sub-processes. So, to effectively guarantee consistency, it is important to implement processes in a way that does take the optimistic, transactional execution model into consideration.

#### Graphical Notation

A transaction sub-process is visualized as a an [embedded sub-process](bpmn/ch07b-BPMN-Constructs.md#graphical-notation) with a double outline.



#### XML representation

A transaction sub-process is represented in XML using the transaction tag:

    <transaction id="myTransaction" >
        ...
    </transaction>

#### Example

The following is an example of a transaction sub-process:



### Call activity (sub-process)

#### Description

BPMN 2.0 makes a distinction between a regular *[sub-process](bpmn/ch07b-BPMN-Constructs.md#aocess)*, often also called *embedded sub-process*, and the call activity, which looks very similar. From a conceptual point of view, both will call a sub-process when the 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 *[sub-process](bpmn/ch07b-BPMN-Constructs.md#aocess)* 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.

When process execution arrives at the *call activity*, a new execution is created that is a sub-execution of the execution that arrived at the call activity. This sub-execution is then used to execute the sub-process, potentially creating parallel child executions, as within a regular process. The super-execution waits until the sub-process has completely ended, and continues with the original process afterwards.

#### Graphical Notation

A call activity is visualized in the same way as a [sub-process](bpmn/ch07b-BPMN-Constructs.md#graphical-notation), but with a thick border (collapsed and expanded). Depending on the modeling tool, a call activity can also be expanded, but the default visualization is the collapsed sub-process representation.



#### XML representation

A call activity is a regular activity, which requires a *calledElement* that 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 sub-process is **resolved at runtime**. This means that the sub-process can be deployed independently from the calling process, if needed.

#### Passing variables

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

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

You can pass all process variables to the sub-process by setting the option inheritVariables to true.

    <callActivity id="callSubProcess" calledElement="checkCreditProcess" flowable:inheritVariables="true"/>

We provide a Flowable Extension as a shortcut for the BPMN standard elements, named *dataInputAssociation* and *dataOutputAssociation*, which only work if you declare process variables in the BPMN 2.0 standard way.

It is possible to use expressions here as well:

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

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

The callActivity element also supports setting the business key on the sub-process instance using a custom Flowable attribute extension. The 'businessKey' attribute can be used to set a custom business key value on the sub-process instance.

    <callActivity id="callSubProcess" calledElement="checkCreditProcess" flowable:businessKey="${myVariable}">
    ...
    </callActivity>

Defining the 'inheritBusinessKey' attribute with a value of true will set the business key value on the sub-process to the value of the business key as defined in the calling process.

    <callActivity id="callSubProcess" calledElement="checkCreditProcess" flowable:inheritBusinessKey="true">
    ...
    </callActivity>

#### Reference the process from the same deployment

The default behavior is that the latest deployed process definition is taken to start the referenced process. There are use cases where
you would like to deploy the referenced process from the same deployment as the main process to use the same state of the referenced
process at the time of the deployment. This requires that you deploy the main and the referenced process within the same deployment unit, such
that the process definitions have the same reference to the deployment.

To use the referenced process from the same deployment you can set the `sameDeployment` attribute to `true` on the `callActivity` element
like in the following example:

    <callActivity id="callSubProcess" calledElement="checkCreditProcess" flowable:sameDeployment="true">
    ...
    </callActivity>

By default the `sameDeployment` attribute is set to false.

The callActivity element provides fallback option in the case when process definition was not found by key in the current tenant. When attribute fallbackToDefaultTenant is set to true.
callActivity searches for process definition by key in definitions without tenant.

    <callActivity id="callSubProcess" calledElement="checkCreditProcess" flowable:fallbackToDefaultTenant="true" >
    ...
    </callActivity>

The default value is `false`.

#### Reference the process definition by id

The default behavior is that the latest deployed process definition is taken to start the referenced process by key. There are use cases where
you would like to reference exact process definition by its id.

To use the referenced process definition by its id use `flowable:calledElementType` with the value `id`. Allowed values are `key` and `id`.

    <callActivity id="callSubProcess" calledElement="UNIQUE-PROCESS_DEFINITION-ID" flowable:calledElementType="id">
    ...
    </callActivity>

By default the `flowable:calledElementType` attribute is set to `key`.

#### Example

The following process diagram shows a simple handling of an order. As the checking of the customer’s credit could be common to many other processes, the *check credit step* is modeled here as a call activity.



The process looks as follows:

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

    <manualTask id="receiveOrder" name="Receive Order" />
    <sequenceFlow id="flow2" sourceRef="receiveOrder" targetRef="callCheckCreditProcess" />

    <callActivity id="callCheckCreditProcess" name="Check credit" calledElement="checkCreditProcess" />
    <sequenceFlow id="flow3" sourceRef="callCheckCreditProcess" targetRef="prepareAndShipTask" />

    <userTask id="prepareAndShipTask" name="Prepare and Ship" />
    <sequenceFlow id="flow4" sourceRef="prepareAndShipTask" targetRef="end" />

    <endEvent id="end" />

The sub-process looks as follows:



There is nothing special about the process definition of the sub-process. It could as well be used without being called from another process.

#### Async completion

In some particular use cases, it’s needed to make the completion of the call activity asynchronous (and exclusive).

Take the following process definition. Let’s assume the called process definition consists of *only service tasks which are marked as asynchronous and exclusive*.
All the steps of these sub process instances will be executed asynchronously. When the last asynchronous service task is executed, the end event will be visited.
At that point, the control will be passed back to the parent process instance.



The problem is that asynchronous locking happens on the process instance level. In this cases, the child process instances will be locked when the last service task and event event are visited.
This means that when the control is passed back to the parent process instance, and thus when the call activity *completes*, the parent process instance is not locked. When multi-instance is used, this means that x number of instances try to complete the call activity. Even when using exclusive on all steps, this still would mean every child process instance concurrently will try to update the parent process instance, potentially leading to *FlowableOptimisticLockingExceptions* as the 'wrong' process instance is used for the exclusive lock.

The solution to this problem is to mark the *async complete* flag for the call activity. When *true*, a new asynchronous job will be created, using the parent process instance.
When the exclusive lock is created, it will be held for parent process instance and the multi instance completion of the call activity will be handled exclusively for each child execution separately.

## Transactions and Concurrency

### Asynchronous Continuations

Flowable executes processes in a transactional way that can be configured to suite your needs. Let’s start by looking at how Flowable scopes transactions normally. If you trigger Flowable (start a process, complete a task, signal an execution), Flowable is going to advance in the process until it reaches wait states on each active path of execution. More concretely speaking, it performs a depth-first search through the process graph and returns if it has reached wait states on every branch of execution. A wait state is a task that is performed "later", which means that Flowable persists the current execution and waits to be triggered again. The trigger can either come from an external source, for example, if we have a user task or a receive message task, or from Flowable itself if we have a timer event. This is illustrated in the following picture:



We see a segment of a BPMN process with a user task, a service task and a timer event. Completing the user task and validating the address is part of the same unit of work, so it should succeed or fail atomically. That means that if the service task throws an exception, we want to rollback the current transaction, such that the execution tracks back to the user task and the user task is still present in the database. This is also the default behavior of Flowable. In (1) an application or client thread completes the task. In that same thread, Flowable is now executing the service and advances until it reaches a wait state, in this case, the timer event (2). Then it returns the control to the caller (3), potentially committing the transaction (if it was started by Flowable).

In some cases this is not what we want. Sometimes we need custom control over transaction boundaries in a process, in order to be able to scope logical units of work. This is where asynchronous continuations come into play. Consider the following process (fragment):



This time we are completing the user task, generating an invoice and then sending that invoice to the customer. This time the generation of the invoice is not part of the same unit of work, so we do not want to rollback the completion of the user task if generating an invoice fails. What we want Flowable to do is complete the user task (1), commit the transaction and return the control to the calling application. Then we want to generate the invoice asynchronously, in a background thread. This background thread is the Flowable job executor (actually a thread pool) that periodically polls the database for jobs. Behind the scenes, when we reach the "generate invoice" task, we are creating a job "message" for Flowable to continue the process later and persisting it into the database. This job is then picked up by the job executor and executed. We are also giving the local job executor a little hint that there is a new job, to improve performance.

In order to use this feature, we can use the *flowable:async="true"* extension. So, for example, the service task would look like this:

    <serviceTask id="service1" name="Generate Invoice"
        flowable:class="my.custom.Delegate"
        flowable:async="true" />

*flowable:async* can be specified on the following BPMN task types: task, serviceTask, scriptTask, businessRuleTask, sendTask, receiveTask, userTask, subProcess, callActivity

On a userTask, receiveTask or other wait states, the async continuation allows us to execute the start execution listeners in a separate thread/transaction.

### Fail Retry

Flowable, in its default configuration, reruns a job three times if there’s any exception in the execution of a job. This is also true for asynchronous jobs. In some cases more flexibility is required, and two additional parameters can be configured:

-   Number of retries

-   Delay between retries

These parameters can be configured by the flowable:failedJobRetryTimeCycle element. Here is a sample usage:

    <serviceTask id="failingServiceTask" flowable:async="true"
        flowable:class="org.flowable.engine.test.jobexecutor.RetryFailingDelegate">

        <extensionElements>
            <flowable:failedJobRetryTimeCycle>R5/PT7M</flowable:failedJobRetryTimeCycle>
        </extensionElements>
    </serviceTask>

Time cycle expression follows ISO 8601 standard, just like timer event expressions. The example above makes the job executor retry the job 5 times and wait 7 minutes between before each retry.

### Exclusive Jobs

In recent releases, the JobExecutor makes sure that jobs from a single process instance are never executed concurrently. Why is this?

#### Why exclusive Jobs?

Consider the following process definition:



We have a parallel gateway followed by three service tasks that all perform an asynchronous continuation. As a result of this, three jobs are added to the database. Once such a job is present in the database it can be processed by the JobExecutor. The JobExecutor acquires the jobs and delegates them to a thread pool of worker threads that actually process the jobs. This means that by using an asynchronous continuation, you can distribute the work to this thread pool (and in a clustered scenario even across multiple thread pools in the cluster). This is usually a good thing. However, it also has an inherent problem: consistency. Consider the parallel join after the service tasks. When execution of a service task is completed, we arrive at the parallel join and need to decide whether to wait for the other executions or whether we can move forward. That means, for each branch arriving at the parallel join, we need to take a decision whether we can continue or whether we need to wait for one or more other executions on the other branches.

Why is this a problem? As the service tasks are configured using an asynchronous continuation, it is possible that the corresponding jobs are all acquired at the same time and delegated to different worker threads by the JobExecutor. The consequence is that the transactions in which the services are executed and in which the three individual executions arrive at the parallel join can overlap. If they do so, each individual transaction will not "see", that another transaction is arriving at the same parallel join concurrently and therefore assume that it has to wait for the others. However, if each transaction assumes that it has to wait for the other ones, none will continue the process after the parallel join and the process instance will remain in that state forever.

How does Flowable address this problem? Flowable performs optimistic locking. Whenever we take a decision based on data that might not be current (because another transaction might modify it before we commit), we make sure to increment the version of the same database row in both transactions. This way, whichever transaction commits first wins and the other ones fail with an optimistic locking exception. This solves the problem in the case of the process discussed above: if multiple executions arrive at the parallel join concurrently, they all assume that they have to wait, increment the version of their parent execution (the process instance) and then try to commit. Whichever execution is first will be able to commit and the other ones will fail with an optimistic locking exception. As the executions are triggered by a job, Flowable will retry to perform the same job after waiting for a certain amount of time and hopefully this time pass the synchronizing gateway.

Is this a good solution? As we have seen, optimistic locking allows Flowable to prevent inconsistencies. It makes sure that we do not "stay stuck at the joining gateway", meaning: either all executions have passed the gateway, or there are jobs in the database making sure that we retry passing it. However, while this is a perfectly fine solution from the point of view of persistence and consistency, this might not always be desirable behavior at a higher level:

-   Flowable will retry the same job for a fixed maximum number of times only ('3' in the default configuration). After that, the job will still be present in the database but will not be retried actively anymore. That means that an external operator would need to trigger the job manually.

-   If a job has non-transactional side effects, these will not be rolled back by the failing transaction. For instance, if the "book concert tickets" service does not share the same transaction as Flowable, we might book multiple tickets if we retry the job.

#### What are exclusive jobs?

An exclusive job cannot be performed at the same time as another exclusive job from the same process instance. Consider the process shown above: if we declare the service tasks to be exclusive, the JobExecutor will make sure that the corresponding jobs are not executed concurrently. Instead, it will make sure that whenever it acquires an exclusive job from a certain process instance, it acquires all other exclusive jobs from the same process instance and delegate them to the same worker thread. This ensures sequential execution of the jobs.

How can I enable this feature? In recent releases, exclusive jobs are the default configuration. All asynchronous continuations and timer events are exclusive by default. In addition, if you want a job to be non-exclusive, you can configure it as such using flowable:exclusive="false". For example, the following service task is asynchronous but non-exclusive.

    <serviceTask id="service" flowable:expression="${myService.performBooking(hotel, dates)}"
        flowable:async="true" flowable:exclusive="false" />

Is this a good solution? We’ve had some people asking whether this was a good solution. Their concern was that this would prevent you from "doing things" in parallel and would consequently be a performance problem. Again, two things have to be taken into consideration:

-   It can be turned off if you’re an expert and know what you are doing (and have understood the section on "Why exclusive Jobs?"). Other than that, it’s more intuitive for most users if things such as asynchronous continuations and timers just work.

-   It’s not actually a performance issue. Performance is an issue under heavy load. Heavy load means that all worker threads of the job executor are busy all the time. With exclusive jobs, Flowable will simply distribute the load differently. Exclusive jobs means that jobs from a single process instance are performed by the same thread sequentially. But consider: you have more than one single process instance. Jobs from other process instances are delegated to other threads and executed concurrently. This means that with exclusive jobs, Flowable will not execute jobs from the same process instance concurrently, but it will still execute multiple instances concurrently. From an overall throughput perspective, this is desirable in most scenarios as it usually leads to individual instances being done more quickly. Furthermore, data that is required for executing subsequent jobs of the same process instance will already be in the cache of the executing cluster node. If the jobs do not have this node affinity, that data might need to be fetched from the database again.

## Process Initiation Authorization

By default, everyone is allowed to start a new process instance of deployed process definitions. The process initiation authorization functionality allows you to define users and groups so that web clients can optionally restrict the users who can start a new process instance. NOTE that the authorization definition is NOT validated by the Flowable engine in any way. This functionality is only meant for developers to ease the implementation of authorization rules in a web client. The syntax is similar to the syntax of user assignment for a user task. A user or group can be assigned as the potential initiator of a process using &lt;flowable:potentialStarter&gt; tag. Here is an example:

    <process id="potentialStarter">
      <extensionElements>
        <flowable:potentialStarter>
           <resourceAssignmentExpression>
             <formalExpression>group2, group(group3), user(user3)</formalExpression>
           </resourceAssignmentExpression>
        </flowable:potentialStarter>
      </extensionElements>

      <startEvent id="theStart"/>
      ...

In the above XML excerpt, 'user(user3)' refers directly to the user 'user3', and 'group(group3)' to group 'group3'. No indicator will default to a group type. It is also possible to use attributes of the &lt;process&gt; tag, namely &lt;flowable:candidateStarterUsers&gt; and &lt;flowable:candidateStarterGroups&gt;. Here is an example:

    <process id="potentialStarter" flowable:candidateStarterUsers="user1, user2"
        flowable:candidateStarterGroups="group1">
        ...

It is possible to use both attributes simultaneously.

After the process initiation authorizations are defined, a developer can retrieve the authorization definition using the following methods.
This code retrieves the list of process definitions that can be initiated by the given user:

    processDefinitions = repositoryService.createProcessDefinitionQuery().startableByUser("userxxx").list();

It’s also possible to retrieve all identity links that are defined as potential initiators for a specific process definition

    identityLinks = repositoryService.getIdentityLinksForProcessDefinition("processDefinitionId");

The following example shows how to get list of users who can initiate the given process:

    List<User> authorizedUsers = identityService().createUserQuery()
        .potentialStarter("processDefinitionId")
        .list();

In exactly the same way, the list of groups that is configured as a potential starter to a given process definition can be retrieved:

    List<Group> authorizedGroups = identityService().createGroupQuery()
        .potentialStarter("processDefinitionId")
        .list();

## Data objects

BPMN provides the possibility to define data objects as part of a process or sub process element. According to the BPMN specification it’s possible to include complex XML structures that might be imported from XSD definitions. As a first start to support data objects in Flowable the following XSD types are supported:

    <dataObject id="dObj1" name="StringTest" itemSubjectRef="xsd:string"/>
    <dataObject id="dObj2" name="BooleanTest" itemSubjectRef="xsd:boolean"/>
    <dataObject id="dObj3" name="DateTest" itemSubjectRef="xsd:datetime"/>
    <dataObject id="dObj4" name="DoubleTest" itemSubjectRef="xsd:double"/>
    <dataObject id="dObj5" name="IntegerTest" itemSubjectRef="xsd:int"/>
    <dataObject id="dObj6" name="LongTest" itemSubjectRef="xsd:long"/>

The data object definitions will be automatically converted to process variables using the 'name' attribute value as the name for the new variable. In addition to the definition of the data object, Flowable also provides an extension element to assign a default value to the variable. The following BPMN snippet provides an example:

    <process id="dataObjectScope" name="Data Object Scope" isExecutable="true">
      <dataObject id="dObj123" name="StringTest123" itemSubjectRef="xsd:string">
        <extensionElements>
          <flowable:value>Testing123</flowable:value>
        </extensionElements>
      </dataObject>
      ...

---

### Docusaurus Docs Bpmn Ch08 ProcessInstanceMigration (`docs/docusaurus/docs/bpmn/ch08-ProcessInstanceMigration.md`)

---
id: ch08-ProcessInstanceMigration
title: Process Instance Migration
---

When process definitions are updated with new versions, the question arises what should be done with already running process instances that are using older versions of the process definition.
In case running process instances should be migrated to another process definition version, you can use the process instance migration features on the Flowable Engine.

## Simple example

Let’s start with a simple example to explain the basics of process instance migration in the Flowable Engine.
In this simple example we use the following use case:

-   There’s one process instance running with a process definition that has a key named simpleTasks and it consists of a start event - user task 1 - end event.

-   The running process instance has an active state of user task 1.

-   A new process definition is deployed with the same key (simpleTasks) and the process definition now consists of a start event - user task 1 - user task 2 - end event.

-   The running process instance should be migrated to the new process definition.

To test if the process instance can be migrated without issues the following code can be used:

    ProcessInstanceMigrationValidationResult validationResult = processMigrationService.createProcessInstanceMigrationBuilder()
        .migrateToProcessDefinition(version2ProcessDef.getId())
        .validateMigration(processInstanceToMigrate.getId());

    boolean isMigrationValid = validationResult.isMigrationValid();

The process instance migration builder can be used to validate and, as we will see later on, migrate one or more process instances.
In this case we test if the running process instance can be migrated to the new process definition version with 2 user tasks.
Because the user task id didn’t change between the two process definition versions, the process instance can be migrated without any additional mapping configuration.
Therefore, the migration will have a migration valid boolean value of true. This means we can run the actual migration without to be expected issues.

    processMigrationService.createProcessInstanceMigrationBuilder()
        .migrateToProcessDefinition(version2ProcessDef.getId())
        .migrate(processInstanceToMigrate.getId());

After executing the migrate method, the running process instance is migrated to the new process definition (including the historic information).
This means that when user task 1 is completed, user task 2 will be the next active state for the running process instance.

## Migration with activity migration mappings

In the simple example user task 1 was automatically mapped to the same user task in the new process definition version.
But in some cases the current activity of a running process instance doesn’t exist anymore in the new process definition, or the activity should be migrated to another activity for another reason.
For this use case, the process instance migration builder allows you to specify a list of specific activity migration mappings.

    processMigrationService.createProcessInstanceMigrationBuilder()
        .migrateToProcessDefinition(version2ProcessDef.getId())
        .addActivityMigrationMapping("userTask1Id", "userTask2Id")
        .migrate(processInstanceToMigrate.getId());

In this example running process instance with an active state of user task 1 will be migrated to a new process definition version with 2 user tasks, and the active state will be migrated to user task 2.
This means that when user task 2 is completed the process instance will be ended.

## Supported process instance migration cases

This section provides an overview of the supported cases for process instance migration.
If the case you are looking for is not yet supported have a look at next section with upcoming support.

-   automatic migration of wait states (user task, receive task, intermediate catch events) to activities with the same id in the new process definition version.

-   manual migration of wait states by specifying the target activity for a specific active state in the running process instance.

-   migrating a wait state to an activity with a boundary timer, signal or message event.

-   migrating a wait state with a boundary timer, signal or message event to an activity without a boundary event.

-   migrating a wait state to an activity in an embedded sub process or a nested embedded subprocess.

-   migrating a wait state in an embedded sub process or a nested embedded sub process to the root level of the process definition or another nested scope.

-   migrating a wait state to an activity in an (nested) event sub process, both interrupting and non-interrupting.

-   migrating multiple executions when using a parallel or inclusive gateway, to one execution outside of the gateway scope.

-   migrating from a single execution to multiple executions within a parallel or inclusive gateway.

-   migrating a wait state to an activity in the parent process.

## Upcoming process instance migration support

With this version of the Flowable Engine the first step with process instance migration support is added. In the next version the focus is on adding support for the following migration cases:

-   Support to move a collection of multi instance executions to another activity.

-   Support to move a wait state to a multi instance activity.

-   Support to move a wait state to an activity in a sub process, when one or more call activities are present in the process definition.

-   Support to add and remove variables in the process instance or local execution scope.

-   Support to define the assignment rules and other configuration options of a target user task.

---

### Docusaurus Docs Bpmn Ch09 JPA (`docs/docusaurus/docs/bpmn/ch09-JPA.md`)

---
id: ch09-JPA
title: JPA
---

You can use JPA-Entities as process variables, allowing you to:

-   Updating existing JPA-entities based on process variables that can be filled in on a form in a userTask or generated in a serviceTask.

-   Reusing existing domain model without having to write explicit services to fetch the entities and update the values

-   Make decisions (gateways) based on properties of existing entities.

-   …​

## Requirements

Only entities that comply with the following are supported:

-   Entities should be configured using JPA-annotations, we support both field and property-access. Mapped super classes can also be used.

-   Entity should have a primary key annotated with @Id, compound primary keys are not supported (@EmbeddedId and @IdClass). The Id field/property can be of any type supported in the JPA-spec: Primitive types and their wrappers (excluding boolean), String, BigInteger, BigDecimal, java.util.Date and java.sql.Date.

## Configuration

To be able to use JPA-entities, the engine must have a reference to an EntityManagerFactory. This can be done by configuring a reference or by supplying a persistence-unit name. JPA-entities used as variables will be detected automatically and will be handled accordingly.

The example configuration below uses the jpaPersistenceUnitName:

    <bean id="processEngineConfiguration"
      class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">

    
    <property name="databaseSchemaUpdate" value="true" />
    <property name="jdbcUrl" value="jdbc:h2:mem:JpaVariableTest;DB_CLOSE_DELAY=1000" />

    <property name="jpaPersistenceUnitName" value="flowable-jpa-pu" />
    <property name="jpaHandleTransaction" value="true" />
    <property name="jpaCloseEntityManager" value="true" />

    
    <property name="asyncExecutorActivate" value="false" />

    
    <property name="mailServerPort" value="5025" />
    </bean>

The next example configuration below provides a EntityManagerFactory which we define ourselves (in this case, an open-jpa entity manager). Note that the snippet only contains the beans that are relevant for the example, the others are omitted. Full working example with open-jpa entity manager can be found in the flowable-spring-examples (/flowable-spring/src/test/java/org/flowable/spring/test/jpa/JPASpringTest.java)

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="persistenceUnitManager" ref="pum"/>
      <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
          <property name="databasePlatform" value="org.apache.openjpa.jdbc.sql.H2Dictionary" />
        </bean>
      </property>
    </bean>

    <bean id="processEngineConfiguration" class="org.flowable.spring.SpringProcessEngineConfiguration">
      <property name="dataSource" ref="dataSource" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="databaseSchemaUpdate" value="true" />
      <property name="jpaEntityManagerFactory" ref="entityManagerFactory" />
      <property name="jpaHandleTransaction" value="true" />
      <property name="jpaCloseEntityManager" value="true" />
      <property name="asyncExecutorActivate" value="false" />
    </bean>

The same configurations can also be done when building an engine programmatically, example:

    ProcessEngine processEngine = ProcessEngineConfiguration
        .createProcessEngineConfigurationFromResourceDefault()
        .setJpaPersistenceUnitName("flowable-pu")
        .buildProcessEngine();

Configuration properties:

-   jpaPersistenceUnitName: The name of the persistence-unit to use. (Make sure the persistence-unit is available on the classpath. According to the spec, the default location is /META-INF/persistence.xml). Use either jpaEntityManagerFactory or jpaPersistenceUnitName.

-   jpaEntityManagerFactory: An reference to a bean implementing jakarta.persistence.EntityManagerFactory that will be used to load the Entities and flushing the updates. Use either *jpaEntityManagerFactory* or *jpaPersistenceUnitName*.

-   jpaHandleTransaction: Flag indicating that the engine should begin and commit/rollback the transaction on the used *EntityManager* instances. Set to false when *Java Transaction API (JTA)* is used.

-   jpaCloseEntityManager: Flag indicating that the engine should close the EntityManager instance that was obtained from the EntityManagerFactory. Set to false when the *EntityManager* is container-managed (e.g. when using an Extended Persistence Context which isn’t scoped to a single transaction').

## Usage

### Simple Example

Examples for using JPA variables can be found in JPAVariableTest in the Flowable source code. We’ll explain JPAVariableTest.testUpdateJPAEntityValues step by step.

First of all, we create an *EntityManagerFactory* for our persistence-unit, which is based on META-INF/persistence.xml. This contains classes which should be included in the persistence unit and some vendor-specific configuration.

We are using a simple entity in the test, having an id and String value property, which is also persisted. Before running the test, we create an entity and save this.

    @Entity(name = "JPA_ENTITY_FIELD")
    public class FieldAccessJPAEntity {

      @Id
      @Column(name = "ID_")
      private Long id;

      private String value;

      public FieldAccessJPAEntity() {
        // Empty constructor needed for JPA
      }

      public Long getId() {
        return id;
      }

      public void setId(Long id) {
        this.id = id;
      }

      public String getValue() {
        return value;
      }

      public void setValue(String value) {
        this.value = value;
      }
    }

We start a new process instance, adding the entity as a variable. As with other variables, they are stored in the persistent storage of the engine. When the variable is requested the next time, it will be loaded from the EntityManager based on the class and Id stored.

    Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("entityToUpdate", entityToUpdate);

    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
        "UpdateJPAValuesProcess", variables);

The first node in our process definition contains a serviceTask that will invoke the method setValue on entityToUpdate, which resolves to the JPA variable we set earlier when starting the process instance and will be loaded from the EntityManager associated with the current engine’s context.

    <serviceTask id='theTask' name='updateJPAEntityTask'
      flowable:expression="${entityToUpdate.setValue('updatedValue')}" />

When the service-task is finished, the process instance waits in a userTask defined in the process definition, which allows us to inspect the process instance. At this point, the EntityManager has been flushed and the changes to the entity have been pushed to the database. When we get the value of the variable entityToUpdate, it’s loaded again and we get the entity with its value property set to updatedValue.

    // Servicetask in process 'UpdateJPAValuesProcess' should have set value on entityToUpdate.
    Object updatedEntity = runtimeService.getVariable(processInstance.getId(), "entityToUpdate");
    assertTrue(updatedEntity instanceof FieldAccessJPAEntity);
    assertEquals("updatedValue", ((FieldAccessJPAEntity)updatedEntity).getValue());

### Query JPA process variables

You can query for ProcessInstances and Executions that have a certain JPA-entity as variable value. **Note that only variableValueEquals(name, entity) is supported for JPA-Entities on ProcessInstanceQuery and ExecutionQuery**. Methods variableValueNotEquals, variableValueGreaterThan, variableValueGreaterThanOrEqual, variableValueLessThan and variableValueLessThanOrEqual are unsupported and will throw an FlowableException when a JPA-Entity is passed as value.

     ProcessInstance result = runtimeService.createProcessInstanceQuery()
        .variableValueEquals("entityToQuery", entityToQuery).singleResult();

### Advanced example using Spring beans and JPA

A more advanced example, JPASpringTest, can be found in flowable-spring-examples. It describes the following simple use case:

-   An existing Spring-bean which uses JPA entities already exists which allows for Loan Requests to be stored.

-   Using Flowable, we can use the existing entities, obtained through the existing bean, and use them as variable in our process. Process is defined in the following steps:

    -   Service task that creates a new LoanRequest, using the existing LoanRequestBean using variables received when starting the process (e.g. could come from a start form). The created entity is stored as a variable, using flowable:resultVariable which stores the expression result as a variable.

    -   UserTask that allows a manager to review the request and approve/disapprove, which is stored as a boolean variable approvedByManager

    -   ServiceTask that updates the loan request entity so the entity is in sync with the process.

    -   Depending on the value of the entity property approved, an exclusive gateway is used to make a decision about what path to take next: When the request is approved, process ends, otherwise, an extra task will become available (Send rejection letter), so the customer can be notified manually by a rejection letter.

Please note that the process doesn’t contain any forms, since it is only used in a unit test.



    <?xml version="1.0" encoding="UTF-8"?>
    <definitions id="taskAssigneeExample"
      xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:flowable="http://flowable.org/bpmn"
      targetNamespace="org.flowable.examples">

      <process id="LoanRequestProcess" name="Process creating and handling loan request">
        <startEvent id='theStart' />
        <sequenceFlow id='flow1' sourceRef='theStart' targetRef='createLoanRequest' />

        <serviceTask id='createLoanRequest' name='Create loan request'
          flowable:expression="${loanRequestBean.newLoanRequest(customerName, amount)}"
          flowable:resultVariable="loanRequest"/>
        <sequenceFlow id='flow2' sourceRef='createLoanRequest' targetRef='approveTask' />

        <userTask id="approveTask" name="Approve request" />
        <sequenceFlow id='flow3' sourceRef='approveTask' targetRef='approveOrDissaprove' />

        <serviceTask id='approveOrDissaprove' name='Store decision'
          flowable:expression="${loanRequest.setApproved(approvedByManager)}" />
        <sequenceFlow id='flow4' sourceRef='approveOrDissaprove' targetRef='exclusiveGw' />

        <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway approval" />
        <sequenceFlow id="endFlow1" sourceRef="exclusiveGw" targetRef="theEnd">
          <conditionExpression xsi:type="tFormalExpression">${loanRequest.approved}</conditionExpression>
        </sequenceFlow>
        <sequenceFlow id="endFlow2" sourceRef="exclusiveGw" targetRef="sendRejectionLetter">
          <conditionExpression xsi:type="tFormalExpression">${!loanRequest.approved}</conditionExpression>
        </sequenceFlow>

        <userTask id="sendRejectionLetter" name="Send rejection letter" />
        <sequenceFlow id='flow5' sourceRef='sendRejectionLetter' targetRef='theOtherEnd' />

        <endEvent id='theEnd' />
        <endEvent id='theOtherEnd' />
      </process>

    </definitions>

Although the example above is quite simple, it shows the power of using JPA combined with Spring and parametrized method-expressions. The process requires no custom Java code at all (except for the Spring-bean off course) and speeds up development drastically.

---

### Docusaurus Docs Bpmn Ch10 History (`docs/docusaurus/docs/bpmn/ch10-History.md`)

---
id: ch10-History
title: History
---

History is the component that captures what happened during process execution and stores it permanently. In contrast to the runtime data, the history data will remain present in the DB also after process instances have completed.

There are 6 history entities:

-   HistoricProcessInstances containing information about current and past process instances.

-   HistoricVariableInstances containing the latest value of a process variable or task variable.

-   HistoricActivityInstances containing information about a single execution of an activity (node in the process).

-   HistoricTaskInstances containing information about current and past (completed and deleted) task instances.

-   HistoricIdentityLinks containing information about current and past identity links on tasks and process instances.

-   HistoricDetails containing various kinds of information related to either a historic process instances, an activity instance or a task instance.

Since the DB contains historic entities for past as well as ongoing instances, you might want to consider querying these tables in order to minimize access to the runtime process instance data and that way keeping the runtime execution performant.

## Querying history

In the API, it’s possible to query all 6 of the History entities. The HistoryService exposes the methods createHistoricProcessInstanceQuery(), createHistoricVariableInstanceQuery(), createHistoricActivityInstanceQuery(), getHistoricIdentityLinksForTask(), getHistoricIdentityLinksForProcessInstance(), createHistoricDetailQuery() and createHistoricTaskInstanceQuery().

Below are a couple of examples that show some of the possibilities of the query API for history. Full description of the possibilities can be found in the [javadocs](http://www.flowable.org/docs/javadocs/index.html), in the org.flowable.engine.history package.

### HistoricProcessInstanceQuery

Get 10 HistoricProcessInstances that are finished and which took the most time to complete (the longest duration) of all finished processes with definition 'XXX'.

    historyService.createHistoricProcessInstanceQuery()
      .finished()
      .processDefinitionId("XXX")
      .orderByProcessInstanceDuration().desc()
      .listPage(0, 10);

### HistoricVariableInstanceQuery

Get all HistoricVariableInstances from a finished process instance with id 'xxx' ordered by variable name.

    historyService.createHistoricVariableInstanceQuery()
      .processInstanceId("XXX")
      .orderByVariableName.desc()
      .list();

### HistoricActivityInstanceQuery

Get the last HistoricActivityInstance of type 'serviceTask' that has been finished in any process that uses the processDefinition with id XXX.

    historyService.createHistoricActivityInstanceQuery()
      .activityType("serviceTask")
      .processDefinitionId("XXX")
      .finished()
      .orderByHistoricActivityInstanceEndTime().desc()
      .listPage(0, 1);

### HistoricDetailQuery

The next example, gets all variable-updates that have been done in process with id 123. Only HistoricVariableUpdates will be returned by this query. Note that it’s possible that a certain variable name has multiple HistoricVariableUpdate entries, for each time the variable was updated in the process. You can use orderByTime (the time the variable update was done) or orderByVariableRevision (revision of runtime variable at the time of updating) to find out in what order they occurred.

    historyService.createHistoricDetailQuery()
      .variableUpdates()
      .processInstanceId("123")
      .orderByVariableName().asc()
      .list()

This example gets all [form-properties](bpmn/ch08-Forms.md#form-properties) that were submitted in any task or when starting the process with id "123". Only HistoricFormProperties will be returned by this query.

    historyService.createHistoricDetailQuery()
      .formProperties()
      .processInstanceId("123")
      .orderByVariableName().asc()
      .list()

The last example gets all variable updates that were performed on the task with id "123". This returns all HistoricVariableUpdates for variables that were set on the task (task local variables), and NOT on the process instance.

    historyService.createHistoricDetailQuery()
      .variableUpdates()
      .taskId("123")
      .orderByVariableName().asc()
      .list()

Task local variables can be set using the TaskService or on a DelegateTask, inside TaskListener:

    taskService.setVariableLocal("123", "myVariable", "Variable value");

    public void notify(DelegateTask delegateTask) {
      delegateTask.setVariableLocal("myVariable", "Variable value");
    }

### HistoricTaskInstanceQuery

Get 10 HistoricTaskInstances that are finished and which took the most time to complete (the longest duration) of all tasks.

    historyService.createHistoricTaskInstanceQuery()
      .finished()
      .orderByHistoricTaskInstanceDuration().desc()
      .listPage(0, 10);

Get HistoricTaskInstances that are deleted with a delete reason that contains "invalid", which were last assigned to user 'kermit'.

    historyService.createHistoricTaskInstanceQuery()
      .finished()
      .taskDeleteReasonLike("%invalid%")
      .taskAssignee("kermit")
      .listPage(0, 10);

## History configuration

The history level can be configured programmatically, using the enum org.flowable.engine.impl.history.HistoryLevel (or *HISTORY* constants defined on ProcessEngineConfiguration for versions prior to 5.11):

    ProcessEngine processEngine = ProcessEngineConfiguration
      .createProcessEngineConfigurationFromResourceDefault()
      .setHistory(HistoryLevel.AUDIT.getKey())
      .buildProcessEngine();

The level can also be configured in flowable.cfg.xml or in a spring-context:

    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
      <property name="history" value="audit" />
      ...
    </bean>

Following history levels can be configured:

-   none: skips all history archiving. This is the most performant for runtime process execution, but no historical information will be available.

-   activity: archives all process instances and activity instances. At the end of the process instance, the latest values of the top level process instance variables will be copied to historic variable instances. No details will be archived.

-   audit: This is the default. It archives all process instances, activity instances, keeps variable values continuously in sync and all form properties that are submitted so that all user interaction through forms is traceable and can be audited.

-   full: This is the highest level of history archiving and hence the slowest. This level stores all information as in the audit level plus all other possible details, mostly this are process variable updates.

**In older releases, the history level was stored in the database (table ACT\_GE\_PROPERTY, property with name historyLevel). Starting from 5.11, this value is not used anymore and is ignored/deleted from the database. The history can now be changed between 2 boots of the engine, without an exception being thrown in case the level changed from the previous engine-boot.**

## History for audit purposes

When [configuring](bpmn/ch10-History.md#history-configuration) at least audit level for configuration. Then all properties submitted through methods FormService.submitStartFormData(String processDefinitionId, Map&lt;String, String&gt; properties) and FormService.submitTaskFormData(String taskId, Map&lt;String, String&gt; properties) are recorded.

Form properties can be retrieved with the query API like this:

    historyService
          .createHistoricDetailQuery()
          .formProperties()
          ...
          .list();

In that case only historic details of type HistoricFormProperty are returned.

If you’ve set the authenticated user before calling the submit methods with IdentityService.setAuthenticatedUserId(String) then that authenticated user who submitted the form will be accessible in the history as well with HistoricProcessInstance.getStartUserId() for start forms and HistoricActivityInstance.getAssignee() for task forms.

## History Cleaning

By default history data is stored forever, this can cause the history tables to grow very large and impact the performance of the HistoryService.  History Cleaning has been introduced with 6.5.0 and allows the deletion of HistoricProcessInstances and their associated data.  Once process data no longer needs to be retained it can be deleted to reduce the history database's size.
The deletion of the historical processes is done using the Flowable Batch mechanism, by scheduling jobs that are going to delete the processes in batches and store the information about what was done in a batch table.

### Automatic History Cleaning Configuration

Automatic cleanup of HistoricProcessInstances is disabled by default but can be enabled and configured programmatically.  Once enabled the default is to run a cleanup job at 1 AM to delete all HistoricProcessInstances and associated data that have ended 365 days prior or older. 

    ProcessEngine processEngine = ProcessEngineConfiguration
        .createProcessEngineConfigurationFromResourceDefault()
        .setEnableHistoryCleaning(true)
        .setHistoryCleaningTimeCycleConfig("0 0 1 * * ?")
        .setCleanInstancesEndedAfter(Duration.ofDays(365))
        .buildProcessEngine();
 
Spring properties set in an application.properties or externalized configuration are also available:
 
         flowable.enable-history-cleaning=true
         flowable.history-cleaning-after=365d
         flowable.history-cleaning-cycle=0 0 1 * * ?
 
Additionally, History Cleanup can also be configured in flowable.cfg.xml or in a spring-context:
 
     <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
       <property name="enableHistoryCleaning" value="true"/>
       <property name="historyCleaningTimeCycleConfig" value="0 0 1 * * ?"/>
       <property name="cleanInstancesEndedAfterNumberOfDays" value="365"/>
       ...
     </bean>

### Manually Deleting History

Manually cleaning history can be accomplished by executing methods on the HistoryService query builders.

Delete all HistoricProcessInstances and their related data that are older than one year.

     int numberOfProcessesInBatch = 10;
     Calendar cal = new GregorianCalendar();
     cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
     historyService.createHistoricProcessInstanceQuery()
       .finishedBefore(cal.getTime())
       .deleteSequentiallyUsingBatch(numberOfProcessesInBatch, "Custom Delete Batch");

---

### Docusaurus Docs Bpmn Ch11 IDM (`docs/docusaurus/docs/bpmn/ch11-IDM.md`)

---
id: ch11-IDM
title: Identity management
---

Starting from Flowable V6, the identity management (IDM) component has been extracted from the flowable-engine module and the logic moved to several separate modules: flowable-idm-api, flowable-idm-engine, flowable-idm-spring and flowable-idm-engine-configurator. The main reason for separating the IDM logic was that it’s not core to the Flowable engine and in a lot of cases when the Flowable engine is embedded in an application, the identity logic is not used or needed.

By default, the IDM engine is initialized and started when the Flowable engine is started. This results in the same identity logic being executed and available in Flowable v5. The idm-engine manages its own database schema and the following entities:

-   User and UserEntity, the user information.

-   Group and GroupEntity, the group information.

-   MembershipEntity, the memberships of users in groups

-   Privilege and PrivilegeEntity, a privilege definition (for example used for controlling access to the UI apps, such as the Flowable Modeler and Flowable Task app)

-   PrivilegeMappingEntity, linking a user and/or group to a privilege

-   Token and TokenEntity, an authentication token used by the UI apps

Since the DB contains historic entities for past as well as ongoing instances, you might want to consider querying these tables in order to minimize access to the runtime process instance data, and that way keep the runtime execution performant.

## IDM engine configuration

By default the Flowable engine is started with the org.flowable.idm.engine.configurator.IdmEngineConfigurator. This configurator uses the same datasource configuration as the Flowable process engine configuration. No additional configuration is needed to use the identity component as it was configured in Flowable v5.

When no identity logic is needed in the Flowable engine the IDM engine can be disabled in the process engine configuration.

    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
      <property name="disableIdmEngine" value="true" />
      ...
    </bean>

This means that no user and group queries can be used, and candidate groups in a task query can not be retrieved for a user.

By default, the user passwords will be saved in plain text in the IDM database tables. To make sure that the passwords are encoded you can define a password encoder in the process engine configuration.

    <bean id="bCryptEncoder"
          class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

    <bean id="passwordEncoder" class="org.flowable.idm.spring.authentication.SpringEncoder">
        <constructor-arg ref="bCryptEncoder"/>
    </bean>

    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
      <property name="passwordEncoder" ref="passwordEncoder" />
      ...
    </bean>

In this example the ShaPasswordEncoder is used, but you can also use the org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder for example. When not using Spring you can also use the org.flowable.idm.engine.impl.authentication.ApacheDigester to encode the passwords.

The default IDM engine configurator can also be overridden to initialize the IDM Engine in a custom way. A good example is the LDAPConfigurator
implementation which overrides the default IDM engine to use a LDAP server instead of the default IDM database tables. The idmProcessEngineConfigurator property of the process engine configuration can be used to set a custom configurator like the LDAPConfigurator

    <bean id="processEngineConfiguration" class="...SomeProcessEngineConfigurationClass">
        ...
        <property name="idmProcessEngineConfigurator">
          <bean class="org.flowable.ldap.LDAPConfigurator">

            
            <property name="server" value="ldap://localhost" />
            <property name="port" value="33389" />
            <property name="user" value="uid=admin, ou=users, o=flowable" />
            <property name="password" value="pass" />

            
            <property name="baseDn" value="o=flowable" />
            <property name="queryUserByUserId" value="(&(objectClass=inetOrgPerson)(uid={0}))" />
            <property name="queryUserByFullNameLike" value="(&(objectClass=inetOrgPerson)(|({0}=*{1}*)({2}=*{3}*)))" />
            <property name="queryGroupsForUser" value="(&(objectClass=groupOfUniqueNames)(uniqueMember={0}))" />

            
            <property name="userIdAttribute" value="uid" />
            <property name="userFirstNameAttribute" value="cn" />
            <property name="userLastNameAttribute" value="sn" />
            <property name="userEmailAttribute" value="mail" />


            <property name="groupIdAttribute" value="cn" />
            <property name="groupNameAttribute" value="cn" />

          </bean>
        </property>
    </bean>

---

### Docusaurus Docs Bpmn Ch12 Design (`docs/docusaurus/docs/bpmn/ch12-Design.md`)

---
id: ch12-Design
title: Flowable Design
---

For modeling a CMMN, BPMN or DMN model there is the Flowable Cloud Design tool for which you can signup for free.

## Signing up

Go to <https://www.flowable.com/account/open-source> and signup for a new account. You will receive an email with a link to setup a password
and then you will be able to sign-in to the Flowable Cloud landing page. From there you can go to the Flowable Cloud Design application and start modeling.
You can also use the following tutorial link to get more information on how to get started with Flowable Cloud Design <https://documentation.flowable.com/latest/howto/tutorial/how-put-together>.

---

### Docusaurus Docs Bpmn Ch13 Applications (`docs/docusaurus/docs/bpmn/ch13-Applications.md`)

---
id: ch13-Applications
title: Flowable applications
---

Flowable provides the `flowable-rest.war` which contains the Flowable REST API. More about this can be read in the [REST API](bpmn/ch14-REST.md) chapter.

The application is a Spring Boot 3.1 based application, which means that the WAR file is actually executable and can be run as a normal standalone application.
See [The Executable Jar Format](https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html#build-tool-plugins-maven-packaging) in the Spring Boot reference documentation.


## Flowable REST application installation

As mentioned before, the application can be deployed on a Tomcat server, and to get started this is probably the easiest approach when additional configuration settings are used. For this installation guide we’ll describe the installation of the application in a Tomcat server.

1.  Download a recent stable version of [Apache Tomcat](http://tomcat.apache.org). It has to be Jakarta Servlet 6 compliant (Tomcat 10 or later)

2.  Download the latest stable [Flowable 7 version](http://www.flowable.org/downloads.html).

3.  Copy the flowable-rest.war file from the Flowable distribution *wars* folder to the Tomcat webapps folder.

4.  Startup the Tomcat server by running the bin/startup.sh (Mac OS and Linux) or bin/startup.bat (Windows) script.

5.  Open a web browser and go to [<http://localhost:8080/flowable-rest/docs>](http://localhost:8080/flowable-rest/docs).

The Flowable REST application should now be running with an H2 in-memory database and the Swagger Docs should be shown in your web browser:

The Flowable REST application should now be running with an H2 in-memory database

Usually, you will want to change the default H2 in-memory database configuration to a MySQL or Postgres (or other persistent database) configuration.
You can do this by changing the application.properties file in the *WEB-INF/classes/* directory of the application.
However, it is easier to use the Spring Boot [Externalized Configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html).
An example configuration can be found on [Github](https://github.com/flowable/flowable-engine/blob/main/modules/flowable-app-rest/src/main/resources/flowable-default.properties)
To change the default configuration to MySQL the following changes are needed to the properties file:

    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/flowable?characterEncoding=UTF-8
    spring.datasource.username=flowable
    spring.datasource.password=flowable

This configuration will expect a flowable database to be present in the MySQL server and the REST app will automatically generate the necessary database tables. For Postgres the following changes are necessary:

    spring.datasource.url=jdbc:postgresql://localhost:5432/flowable
    spring.datasource.username=flowable
    spring.datasource.password=flowable

In addition to changing the configuration, make sure the database driver is available on the classpath. Again, you could do this for the web application by adding the driver JAR file to the WEB-INF/lib folder, but you can also copy the JAR file to the Tomcat lib folder. For MySQL and Postgres the database drivers can be downloaded from:

-   MySQL: [<https://dev.mysql.com/downloads/connector/j>](https://dev.mysql.com/downloads/connector/j)

-   Postgres: [<https://jdbc.postgresql.org/>](https://jdbc.postgresql.org/)

When running the REST as a standalone application the database driver can be added by using the `loader.path` property.

    java -Dloader.path=/location/to/your/driverfolder -jar flowable-rest.war

See the [`PropertiesLauncher` Features](https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html#executable-jar-property-launcher-features) in the Spring Boot reference documentation for more information.

## Flowable REST Application Configuration

As the Flowable REST app is a Spring Boot application, you can use all the properties Spring Boot provides.
In order to provide custom configuration for the application have a look at the [Externalized Configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html) section of the Spring Boot documentation.

    You can also use YAML based properties.

<table>
<caption>REST App Properties</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Property name</th>
<th>Old Property</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="even">
<td><p>flowable.rest.app.authentication-mode</p></td>
<td><p>rest.authentication.mode</p></td>
<td><p>verify-privilege</p></td>
<td><p>Configures the way user credentials are verified when doing a REST API call:
'any-user' : the user needs to exist and the password need to match. Any user is allowed to do the call (this is the pre 6.3.0 behavior)
'verify-privilege' : the user needs to exist, the password needs to match and the user needs to have the 'rest-api' privilege
If nothing set, defaults to 'verify-privilege'</p></td>
</tr>
</tbody>
</table>

Some of the old properties have been moved to be managed by the Flowable Spring Boot starter (or Spring Boot itself)

<table>
<caption>Old properties managed by the Flowable Spring Boot Starter</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Property name</th>
<th>Old Property</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>flowable.async-executor-activate</p></td>
<td><p>engine.process.asyncexecutor.activate</p></td>
<td><p>true</p></td>
<td><p>Whether the async executor should be activated.</p></td>
</tr>
<tr class="even">
<td><p>flowable.database-schema-update</p></td>
<td><p>engine.process.schema.update</p></td>
<td><p>true</p></td>
<td><p>The strategy that should be used for the database schema.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.history-level</p></td>
<td><p>engine.process.history.level</p></td>
<td><p>-</p></td>
<td><p>The history level that needs to be used.</p></td>
</tr>
<tr class="even">
<td><p>flowable.process.servlet.name</p></td>
<td><p>flowable.rest-api-servlet-name</p></td>
<td><p>Flowable BPMN Rest API</p></td>
<td><p>The name of the Process servlet.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.process.servlet.path</p></td>
<td><p>flowable.rest-api-mapping</p></td>
<td><p>/process-api</p></td>
<td><p>The context path for the Process rest servlet.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.enabled</p></td>
<td><p>flowable.db-identity-used</p></td>
<td><p>true</p></td>
<td><p>Whether the idm engine needs to be started.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.password-encoder</p></td>
<td><p>security.passwordencoder</p></td>
<td><p>-</p></td>
<td><p>The type of the password encoder that needs to be used.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.base-dn</p></td>
<td><p>ldap.basedn</p></td>
<td><p>-</p></td>
<td><p>The base 'distinguished name' (DN) from which the searches for users and groups are started. Use 'user-base-dn' or 'group-base-dn' when needing to differentiate between user and group base DN.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.enabled</p></td>
<td><p>ldap.enabled</p></td>
<td><p>false</p></td>
<td><p>Whether to enable LDAP IDM Service.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.password</p></td>
<td><p>ldap.password</p></td>
<td><p>-</p></td>
<td><p>The password that is used to connect to the LDAP system.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.port</p></td>
<td><p>ldap.port</p></td>
<td><p>-1</p></td>
<td><p>The port on which the LDAP system is running.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.server</p></td>
<td><p>ldap.server</p></td>
<td><p>-</p></td>
<td><p>The server host on which the LDAP system can be reached. For example 'ldap://localhost'.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.user</p></td>
<td><p>ldap.user</p></td>
<td><p>-</p></td>
<td><p>The user id that is used to connect to the LDAP system.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.attribute.email</p></td>
<td><p>ldap.attribute.email</p></td>
<td><p>-</p></td>
<td><p>Name of the attribute that matches the user email.
This property is used when looking for an 'org.flowable.idm.api.User' object and the mapping between the LDAP object and the Flowable 'org.flowable.idm.api.User' object is done.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.attribute.first-name</p></td>
<td><p>ldap.attribute.firstname</p></td>
<td><p>-</p></td>
<td><p>Name of the attribute that matches the user first name.
This property is used when looking for a 'org.flowable.idm.api.User' object and the mapping between the LDAP object and the Flowable 'org.flowable.idm.api.User' object is done.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.attribute.group-id</p></td>
<td><p>ldap.attribute.groupid</p></td>
<td><p>-</p></td>
<td><p>Name of the attribute that matches the group id.
This property is used when looking for a 'org.flowable.idm.api.Group' object and the mapping between the LDAP object and the Flowable 'org.flowable.idm.api.Group' object is done.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.attribute.group-name</p></td>
<td><p>ldap.attribute.groupname</p></td>
<td><p>-</p></td>
<td><p>Name of the attribute that matches the group name.
This property is used when looking for a 'org.flowable.idm.api.Group' object and the mapping between the LDAP object and the Flowable 'org.flowable.idm.api.Group' object is done.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.attribute.last-name</p></td>
<td><p>ldap.attribute.lastname</p></td>
<td><p>-</p></td>
<td><p>Name of the attribute that matches the user last name.
This property is used when looking for a 'org.flowable.idm.api.User' object and the mapping between the LDAP object and the Flowable 'org.flowable.idm.api.User' object is done.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.attribute.user-id</p></td>
<td><p>ldap.attribute.userid</p></td>
<td><p>-</p></td>
<td><p>Name of the attribute that matches the user id.
This property is used when looking for a 'org.flowable.idm.api.User' object and the mapping between the LDAP object and the Flowable 'org.flowable.idm.api.User' object is done. This property is optional and is only needed if searching for 'org.flowable.idm.api.User' objects using the Flowable API.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.cache.group-size</p></td>
<td><p>ldap.cache.groupsize</p></td>
<td><p>-1</p></td>
<td><p>Allows to set the size of the 'org.flowable.ldap.LDAPGroupCache'.
This is an LRU cache that caches groups for users and thus avoids hitting the LDAP system each time the groups of a user needs to be known.
The cache will not be instantiated if the value is less then zero. By default set to -1, so no caching is done.
Note that the group cache is instantiated on the 'org.flowable.ldap.LDAPIdentityServiceImpl'.
As such, if you have a custom implementation of the 'org.flowable.ldap.LDAPIdentityServiceImpl', do not forget to add the group cache functionality.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.query.all-groups</p></td>
<td><p>ldap.query.groupall</p></td>
<td><p>-</p></td>
<td><p>The query that is executed when searching for all groups.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.query.all-users</p></td>
<td><p>ldap.query.userall</p></td>
<td><p>-</p></td>
<td><p>The query that is executed when searching for all users.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.query.groups-for-user</p></td>
<td><p>ldap.query.groupsforuser</p></td>
<td><p>-</p></td>
<td><p>The query that is executed when searching for the groups of a specific user.
For example: <code>(&amp;(objectClass=groupOfUniqueNames)(uniqueMember={0}))</code>
Here, all the objects in LDAP with the class 'groupOfUniqueNames' and where the provided DN is a 'uniqueMember' are returned.
As shown in the example, the user id is injected by the typical {@link java.text.MessageFormat}, ie by using <em>{0}</em>
If setting the query alone is insufficient for your specific LDAP setup, you can alternatively plug in a different
<code>org.flowable.ldap.LDAPQueryBuilder</code>, which allows for more customization than only the query.</p></td>
</tr>
<tr class="even">
<td><p>flowable.idm.ldap.query.user-by-full-name-like</p></td>
<td><p>ldap.query.userbyname</p></td>
<td><p>-</p></td>
<td><p>The query that is executed when searching for a user by full name.
For example: <code>(&amp;(objectClass=inetOrgPerson)(|({0}={1})({2}={3})))</code>
Here, all the objects in LDAP with the class 'inetOrgPerson' and who have the matching first name or last name will be returned
Several things will be injected in the expression: {0} : the first name attribute {1} : the search text {2} : the last name attribute {3} : the search text
If setting the query alone is insufficient for your specific LDAP setup, you can alternatively plug in a different
'org.flowable.ldap.LDAPQueryBuilder', which allows for more customization than only the query.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.idm.ldap.query.user-by-id</p></td>
<td><p>ldap.query.userbyid</p></td>
<td><p>-</p></td>
<td><p>The query that is executed when searching for a user by userId.
For example: <code>(&amp;(objectClass=inetOrgPerson)(uid={0}))</code>
Here, all the objects in LDAP with the class 'inetOrgPerson' and who have the matching 'uid' attribute value will be returned.
As shown in the example, the user id is injected by the typical {@link java.text.MessageFormat}, ie by using <em>{0}</em>
If setting the query alone is insufficient for your specific LDAP setup, you can alternatively plug in a different
'org.flowable.ldap.LDAPQueryBuilder', which allows for more customization than only the query.</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.host</p></td>
<td><p>email.host</p></td>
<td><p>localhost</p></td>
<td><p>The host of the mail server.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.password</p></td>
<td><p>email.password</p></td>
<td><p>-</p></td>
<td><p>The password for the mail server authentication.</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.port</p></td>
<td><p>email.port</p></td>
<td><p>1025</p></td>
<td><p>The port of the mail server.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.ssl-port</p></td>
<td><p>email.ssl-port</p></td>
<td><p>1465</p></td>
<td><p>The SSL port of the mail server.</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.use-ssl</p></td>
<td><p>email.use-ssl</p></td>
<td><p>false</p></td>
<td><p>Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS).</p></td>
</tr>
<tr class="odd">
<td><p>flowable.mail.server.use-tls</p></td>
<td><p>email.use-tls</p></td>
<td><p>false</p></td>
<td><p>Set or disable the STARTTLS encryption.</p></td>
</tr>
<tr class="even">
<td><p>flowable.mail.server.username</p></td>
<td><p>email.username</p></td>
<td><p>-</p></td>
<td><p>The username that needs to be used for the mail server authentication.
If empty no authentication would be used.</p></td>
</tr>
<tr class="odd">
<td><p>flowable.process.definition-cache-limit</p></td>
<td><p>flowable.process-definitions.cache.max</p></td>
<td><p>-1</p></td>
<td><p>The maximum amount of process definitions available in the process definition cache.
Per default it is -1 (all process definitions).</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Old properties managed by Spring Boot</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Property name</th>
<th>Old Property</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>spring.datasource.driver-class-name</p></td>
<td><p>datasource.driver</p></td>
<td><p>-</p></td>
<td><p>Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.</p></td>
</tr>
<tr class="even">
<td><p>spring.datasource.jndi-name</p></td>
<td><p>datasource.jndi.name</p></td>
<td><p>-</p></td>
<td><p>JNDI location of the datasource. Class, url, username &amp; password are ignored when
set.</p></td>
</tr>
<tr class="odd">
<td><p>spring.datasource.password</p></td>
<td><p>datasource.password</p></td>
<td><p>-</p></td>
<td><p>Login password of the database.</p></td>
</tr>
<tr class="even">
<td><p>spring.datasource.url</p></td>
<td><p>datasource.url</p></td>
<td><p>-</p></td>
<td><p>JDBC URL of the database.</p></td>
</tr>
<tr class="odd">
<td><p>spring.datasource.username</p></td>
<td><p>datasource.username</p></td>
<td><p>-</p></td>
<td><p>Login username of the database.</p></td>
</tr>
<tr class="even">
<td><p>spring.datasource.hikari.connection-test-query</p></td>
<td><p>datasource.preferred-test-query</p></td>
<td><p>-</p></td>
<td><p>The SQL query to be executed to test the validity of connections.</p></td>
</tr>
<tr class="odd">
<td><p>spring.datasource.hikari.connection-timeout</p></td>
<td><p>datasource.connection.timeout</p></td>
<td><p>-</p></td>
<td><p>The maximum number of milliseconds that a client will wait for a connection from the pool. If this time is exceeded without a connection becoming available, a SQLException will be thrown when getting a connection.</p></td>
</tr>
<tr class="even">
<td><p>spring.datasource.hikari.idle-timeout</p></td>
<td><p>datasource.connection.idletimeout</p></td>
<td><p>-</p></td>
<td><p>The maximum amount of time (in milliseconds) that a connection is allowed to sit idle in the pool.
Whether a connection is retired as idle or not is subject to a maximum variation of +30 seconds, and average variation of +15 seconds.
A connection will never be retired as idle before this timeout.
A value of 0 means that idle connections are never removed from the pool.</p></td>
</tr>
<tr class="odd">
<td><p>spring.datasource.hikari.max-lifetime</p></td>
<td><p>datasource.connection.maxlifetime</p></td>
<td><p>-</p></td>
<td><p>This property controls the maximum lifetime of a connection in the pool. When a connection reaches this
timeout, even if recently used, it will be retired from the pool. An in-use connection will never be
retired, only when it is idle will it be removed.</p></td>
</tr>
<tr class="even">
<td><p>spring.datasource.hikari.maximum-pool-size</p></td>
<td><p>datasource.connection.maxpoolsize</p></td>
<td><p>-</p></td>
<td><p>The property controls the maximum size that the pool is allowed to reach, including both idle and in-use
connections. Basically this value will determine the maximum number of actual connections to the database
backend.
When the pool reaches this size, and no idle connections are available, calls to getConnection() will
block for up to connectionTimeout milliseconds before timing out.</p></td>
</tr>
<tr class="odd">
<td><p>spring.datasource.hikari.minimum-idle</p></td>
<td><p>datasource.connection.minidle</p></td>
<td><p>-</p></td>
<td><p>The property controls the minimum number of idle connections that HikariCP tries to maintain in the pool,
including both idle and in-use connections. If the idle connections dip below this value, HikariCP will
make a best effort to restore them quickly and efficiently.</p></td>
</tr>
<tr class="even">
<td><p>spring.servlet.multipart.max-file-size</p></td>
<td><p>file.upload.max.size</p></td>
<td><p>10MB</p></td>
<td><p>Max file size. Values can use the suffixes "MB" or "KB" to indicate megabytes or kilobytes, respectively.</p></td>
</tr>
</tbody>
</table>

## Flowable LDAP configuration


In addition to the default identity tables, the IDM component can also be configured to use an LDAP server.
To connect to a LDAP server, additional properties in the application.properties file (or any other way of configuring the application) are needed:

    #
    # LDAP
    #
    flowable.idm.ldap.enabled=true
    flowable.idm.ldap.server=ldap://localhost
    flowable.idm.ldap.port=10389
    flowable.idm.ldap.user=uid=admin, ou=system
    flowable.idm.ldap.password=secret
    flowable.idm.ldap.base-dn=o=flowable
    flowable.idm.ldap.query.user-by-id=(&(objectClass=inetOrgPerson)(uid={0}))
    flowable.idm.ldap.query.user-by-full-name-like=(&(objectClass=inetOrgPerson)(|({0}=*{1}*)({2}=*{3}*)))
    flowable.idm.ldap.query.all-users=(objectClass=inetOrgPerson)
    flowable.idm.ldap.query.groups-for-user=(&(objectClass=groupOfUniqueNames)(uniqueMember={0}))
    flowable.idm.ldap.query.all-groups=(objectClass=groupOfUniqueNames)
    flowable.idm.ldap.query.group-by-id=(&(objectClass=groupOfUniqueNames)(uniqueId={0}))
    flowable.idm.ldap.attribute.user-id=uid
    flowable.idm.ldap.attribute.first-name=cn
    flowable.idm.ldap.attribute.last-name=sn
    flowable.idm.ldap.attribute.group-id=cn
    flowable.idm.ldap.attribute.group-name=cn
    flowable.idm.ldap.cache.group-size=10000
    flowable.idm.ldap.cache.group-expiration=180000

When the `flowable.idm.ldap.enabled` property is set to true, the REST app will expect the other LDAP properties to have been filled-in.
In this example configuration the server configuration + LDAP queries for the Apache Directory Server are provided.
For other LDAP servers, like Active Directory, other configuration values are needed.

When LDAP is configured, authentication and group retrieval for a user will be done through the LDAP server. Only privileges will still be retrieved from the Flowable identity tables. So make sure each LDAP user has the correct privileges defined in the IDM app.

If the application is booted with LDAP configuration the bootstrap logic will check if there are already privileges present in the Flowable identity tables.
If there are no privileges (only when booting the first time), the 4 default privileges will be created and the `flowable.rest.app.admin.user-id` property value (from application.properties or configured in the environment) will be used as the user id to get all privileges.
So make sure that the `flowable.rest.app.admin.user-id` property value is set to a valid LDAP user, otherwise nobody will be able to use the Flowable REST app.

## Production-ready endpoints

The [Production ready endpoints](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html) from Spring Boot are present for the application.
To have an overview of all the available Endpoints have a look at the [Actuator Web API Documentation](https://docs.spring.io/spring-boot/docs/current/actuator-api/html/).

This properties are set per default:

    # Expose all actuator endpoints to the web
    # They are exposed, but only authenticated users can see /info and /health abd users with access-admin can see the others
    management.endpoints.web.exposure.include=*
    # Full health details should only be displayed when a user is authorized
    management.endpoint.health.show-details=when_authorized
    # Only users with role access-admin can access full health details
    management.endpoint.health.roles=access-admin

The security is configured in such way that the `info` and `health` endpoint are exposed to all authenticated users.
Full details of the `health` endpoint can only be seen by users with the privilege `access-admin`.
In case you want to change that you need to configure `management.endpoint.health.show-details`.
All the rest of the endpoints are accessing only to users with the `access-admin` privilege.

## Custom bean deployment

There are multiple ways of providing custom beans to the Flowable application.

### Using Spring Boot auto configuration

The Flowable application is a Spring Boot 2 application.
This means that normal Spring Boot auto configuration can be used to make the beans to Flowable.
This can be done in the following manner

    package com.your.own.package.configuration;

    @Configuration
    @AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE) // Makes sure that this configuration will be processed last by Spring Boot
    @ConditionalOnBean(type = "org.flowable.engine.ProcessEngine") // The configuration will only be used when the ProcessEngine bean is present
    public class YourOwnConfiguration {

        @Configuration
        @ComponentScan ("com.your.own.package.beans")
        public static class ComponentScanConfiguration {
            // This class is needed in order to conditionally perform the component scan (i.e. when the ProcessEngine bean is present)
            // It is an optional class, in case you don't need component scanning then you don't need to do this
        }

        @Bean
        public CustomBean customBean() {
            // create your bean
        }

        @Bean
        public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> customProcessEngineConfigurationConfigurer() {
            return engineConfiguration -> {
                // You can use this to add extra configuration to the process engine
            }
        }
    }

Note that when using Spring Boot the configuration class can be under your own package and not under some Flowable package.

In order to make this class an auto configuration class a file named `org.springframework.boot.autoconfigure.AutoConfiguration.imports` should be created in the `META-INF/spring` folder of your jar.
In this file you should add

    com.your.own.package.configuration.YourOwnCustomConfiguration

In order to use this approach you would need to include your jar in the `WEB-INF/lib` folder of the exploded war.
Placing this jar in the lib folder of the servlet container (e.g. Tomcat) is not going to work due to the way Spring proxies the `@Configuration` classes.

### Component scan

Another way to provide custom Spring beans to the Flowable engine is to put them under a certain package and have the Flowable application component scan that package.
Based on the application used, this package is different:

-   `org.flowable.rest.app` for the `flowable-rest.war`

The custom beans can be located in a single JAR and this jar should be present on the classpath when the application is starting up.
Depending where there JAR is placed, the lib folder of the servlet container (e.g. Tomcat) or the `WEB-INF/lib` folder of the exploded war, there are different possibilities.

When using the lib folder of the servlet container then the created classes should be self contained, i.e. they should only use classes from within the jar.
You can use any of the Spring `@Component` annotations (with the exception of `@Configuration`).
The reason for not being able to use `@Configuration` classes is the fact that each configuration class is proxied by Spring with the help of the `ConfigurationClassPostProcessor`.
However, the classloader loading the `@Configuration` class does not have access to the needed classes by Spring.

When including the jar in the `WEB-INF/lib` folder of the exploded war then `@Configuration` classes and dependencies to other jars is possible.

### Creating your own Spring Boot application

This approach is the most flexible and most powerful approach of all.
In order to follow this approach have a look at the [Getting Started with Spring Boot](bpmn/ch05a-Spring-Boot.md#getting-started) section of this documentation.

---

### Docusaurus Docs Bpmn Ch14 REST (`docs/docusaurus/docs/bpmn/ch14-REST.md`)

---
id: ch14-REST
title: REST API
---

## General Flowable REST principles

### Installation and Authentication

Flowable includes a REST API to the Flowable engine that can be installed by deploying the flowable-rest.war file to a servlet container like Apache Tomcat. However, it can also be used in another web-application by including the servlet (and/or its mappings) in your application and add all flowable-rest dependencies to the classpath.

By default the Flowable engine will connect to an in-memory H2 database. You can change the database settings in the flowable-app.properties file in the *WEB-INF/META-INF/flowable-app* folder. The REST API uses JSON format (<http://www.json.org>) and is built upon the Spring MVC (<http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html>).

All REST-resources require a valid user with the *rest-access-api* privilege to be authenticated by default. If any valid user should be able to call the REST API, the *flowable.rest.app.authentication-mode* can be set to *any-user* (this was the default in older versions of Flowable).

A default user that can access the REST API can be configured by settings the following properties:

    flowable.rest.app.admin.user-id=rest-admin
    flowable.rest.app.admin.password=test
    flowable.rest.app.admin.first-name=Rest
    flowable.rest.app.admin.last-name=Admin

When the REST app boots up, the user is created if it doesn’t exist or fetched otherwise. This user will be given the *access-rest-api* privilege which is needed by default to access the REST API. **Do not forget to change the password of this user afterwards**. If the *flowable.rest.app.admin.user-id* is not set, no users or privileges will be created. So, after the initial setup, removing this property will not remove the user nor the privilege that has been configured before.

Basic HTTP access authentication is used, so you should always include a *Authorization: Basic …​==* HTTP-header when performing requests or include the username and password in the request-url (for example, *<http://username:password@localhost:8080/xyz>*).

**We recommend that you use Basic Authentication in combination with HTTPS.**

### Configuration

The Flowable REST web application uses Spring Java Configuration for starting the Flowable Form engine, defining the basic authentication security using Spring security, and to define the variable converters for specific variable handling.
A small number of properties can be defined by changing the flowable-app.properties file you can find in the WEB-INF/META-INF/flowable-app/flowable-app.properties folder.
If you need more advanced configuration options there’s the possibility to override the default Spring beans in XML in the flowable-custom-context.xml file you can also find in the WEB-INF/classes folder.
An example configuration is already in comments in this file. This is also the place to override the default RestResponseFactory by defining a new Spring bean with the name restResponsefactory and use your custom implementation class for it.

### Usage in Tomcat

Due to [default security properties on Tomcat](http://tomcat.apache.org/tomcat-8.0-doc/security-howto.html), **escaped forward slashes (%2F and %5C) are not allowed by default (400-result is returned).** This may have an impact on the deployment resources and their data-URL, as the URL can potentially contain escaped forward slashes.

When issues are experienced with unexpected 400-results, set the following system-property:

*-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW\_ENCODED\_SLASH=true*

It’s best practice to always set the **Accept** and **Content-Type** (in case of posting/putting JSON) headers to **application/json** on the HTTP requests described below.

### Methods and return-codes

<table>
<caption>HTTP-methods and corresponding operations</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>GET</p></td>
<td><p>Get a single resource or get a collection of resources.</p></td>
</tr>
<tr class="even">
<td><p>POST</p></td>
<td><p>Create a new resource. Also used for executing resource-queries which have a too complex request-structure to fit in the query-URL of a GET-request.</p></td>
</tr>
<tr class="odd">
<td><p>PUT</p></td>
<td><p>Update properties of an existing resource. Also used for invoking actions on an existing resource.</p></td>
</tr>
<tr class="even">
<td><p>DELETE</p></td>
<td><p>Delete an existing resource.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>HTTP-methods response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200 - Ok</p></td>
<td><p>The operation was successful and a response has been returned (GET and PUT requests).</p></td>
</tr>
<tr class="even">
<td><p>201 - Created</p></td>
<td><p>The operation was successful and the entity has been created and is returned in the response-body (POST request).</p></td>
</tr>
<tr class="odd">
<td><p>204 - No content</p></td>
<td><p>The operation was successful and entity has been deleted and therefore there is no response-body returned (DELETE request).</p></td>
</tr>
<tr class="even">
<td><p>401 - Unauthorized</p></td>
<td><p>The operation failed. The operation requires an Authentication header to be set. If this was present in the request, the supplied credentials are not valid or the user is not authorized to perform this operation.</p></td>
</tr>
<tr class="odd">
<td><p>403 - Forbidden</p></td>
<td><p>The operation is forbidden and should not be re-attempted. This implies an issue with authorization not authentication, it’s an operation that is not allowed. Example: deleting a task that is part of a running process is not allowed and will never be allowed, regardless of the user or process/task state.</p></td>
</tr>
<tr class="even">
<td><p>404 - Not found</p></td>
<td><p>The operation failed. The requested resource was not found.</p></td>
</tr>
<tr class="odd">
<td><p>405 - Method not allowed</p></td>
<td><p>The operation failed. The method is not allowed for this resource. For example, trying to update (PUT) a deployment-resource will result in a 405 status.</p></td>
</tr>
<tr class="even">
<td><p>409 - Conflict</p></td>
<td><p>The operation failed. The operation causes an update of a resource that has been updated by another operation, which makes the update no longer valid. Can also indicate a resource that is being created in a collection where a resource with that identifier already exists.</p></td>
</tr>
<tr class="odd">
<td><p>415 - Unsupported Media Type</p></td>
<td><p>The operation failed. The request body contains an unsupported media type. Also occurs when the request-body JSON contains an unknown attribute or value that doesn’t have the right format/type to be accepted.</p></td>
</tr>
<tr class="even">
<td><p>500 - Internal server error</p></td>
<td><p>The operation failed. An unexpected exception occurred while executing the operation. The response-body contains details about the error.</p></td>
</tr>
</tbody>
</table>

The media-type of the HTTP-responses is always application/json unless binary content is requested (for example, deployment resource data), the media-type of the content is used.

### Error response body

When an error occurs (both client and server, 4XX and 5XX status-codes) the response body contains an object describing the error that occurred. An example for a 404-status when a task is not found:

    {
      "statusCode" : 404,
      "errorMessage" : "Could not find a task with id '444'."
    }

### Request parameters

#### URL fragments

Parameters that are part of the URL (for example, the deploymentId parameter in http://host/flowable-rest/process-api/repository/deployments/{deploymentId})
need to be properly escaped (see [URL-encoding or Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding)) in case the segment contains special characters. Most frameworks have this functionality built in, but it should be taken into account. Especially for segments that can contain forward-slashes (for example, deployment resource), this is required.

#### Rest URL query parameters

Parameters added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/process-api/repository/deployments?name=Deployment) can have the following types and are mentioned in the corresponding REST-API documentation:

<table>
<caption>URL query parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. Can contain any valid characters that are allowed in URLs. In the case of a XXXLike parameter, the string should contain the wildcard character % (properly URL-encoded). This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Boolean</p></td>
<td><p>Parameter representing a boolean value. Can be either true or false. All other values other than these will cause a '405 - Bad request' response.</p></td>
</tr>
<tr class="odd">
<td><p>Date</p></td>
<td><p>Parameter representing a date value. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (e.g. 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### JSON body parameters

<table>
<caption>JSON parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. In the case of a XXXLike parameter, the string should contain the wildcard character %. This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value, using a JSON number. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value, using a JSON number. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Date</p></td>
<td><p>Parameter representing a date value, using a JSON text. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (for example, 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### Paging and sorting

Paging and order parameters can be added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/process-api/repository/deployments?sort=name).

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>sort</p></td>
<td><p>different per query implementation</p></td>
<td><p>Name of the sort key, for which the default value and the allowed values are different per query implementation.</p></td>
</tr>
<tr class="even">
<td><p>order</p></td>
<td><p>asc</p></td>
<td><p>Sorting order which can be 'asc' or 'desc'.</p></td>
</tr>
<tr class="odd">
<td><p>start</p></td>
<td><p>0</p></td>
<td><p>Parameter to allow for paging of the result. By default the result will start at 0.</p></td>
</tr>
<tr class="even">
<td><p>size</p></td>
<td><p>10</p></td>
<td><p>Parameter to allow for paging of the result. By default the size will be 10.</p></td>
</tr>
</tbody>
</table>

> **Note**
>
> Bear in mind that the start parameter is used as the offset of the query. For example, to get tasks in three pages of three items each (9 items), we would use:
>
>     GET /runtime/tasks?start=0&size=3
>     GET /runtime/tasks?start=3&size=3
>     GET /runtime/tasks?start=6&size=3

#### JSON query variable format

    {
      "name" : "variableName",
      "value" : "variableValue",
      "operation" : "equals",
      "type" : "string"
    }

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>Name of the variable to include in a query. Can be empty in the case where 'equals' is used in some queries to query for resources that have <strong>any variable name</strong> with the given value.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>Yes</p></td>
<td><p>Value of the variable included in the query, should include a correct format for the given type.</p></td>
</tr>
<tr class="odd">
<td><p>operator</p></td>
<td><p>Yes</p></td>
<td><p>Operator to use in query, can have the following values: equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, lessThan, greaterThan, lessThanOrEquals, greaterThanOrEquals and like.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of variable to use. When omitted, the type will be deduced from the value parameter. Any JSON text-values will be considered of type string, JSON booleans of type boolean, JSON numbers of type long or integer depending on the size of the number. We recommended you include an explicit type when in doubt. Types supported out of the box are listed below.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Default query JSON types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as and converted to a java.lang.String.</p></td>
</tr>
<tr class="even">
<td><p>short</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="odd">
<td><p>integer</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as and converted to a java.lang.Long.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as and converted to a java.lang.Double.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as and converted to a java.lang.Boolean.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as and converted to a java.util.Date. The JSON string will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

#### Variable representation

When working with variables (execute decision), the REST API uses some common principles and JSON-format for both reading and writing. The JSON representation of a variable looks like this:

    {
      "name" : "variableName",
      "value" : "variableValue",
      "valueUrl" : "http://...",
      "type" : "string"
    }

<table>
<caption>Variable JSON attributes</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>Yes</p></td>
<td><p>Name of the variable.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>No</p></td>
<td><p>Value of the variable. When writing a variable and value is omitted, null will be used as value.</p></td>
</tr>
<tr class="odd">
<td><p>valueUrl</p></td>
<td><p>No</p></td>
<td><p>When reading a variable of type binary or serializable, this attribute will point to the URL from where the raw binary data can be fetched.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of the variable. See table below for additional information on types. When writing a variable and this value is omitted, the type will be deduced from the raw JSON-attribute request type and is limited to either string, double, integer and boolean. We advise you to always include a type to make sure no wrong assumption about the type are made.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Variable Types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as a java.lang.String. Raw JSON-text value is used when writing a variable.</p></td>
</tr>
<tr class="even">
<td><p>integer</p></td>
<td><p>Value is treated as a java.lang.Integer. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>short</p></td>
<td><p>Value is treated as a java.lang.Short. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as a java.lang.Long. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as a java.lang.Double. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as a java.lang.Boolean. When writing, JSON boolean value is used for conversion.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as a java.util.Date. When writing, the JSON text will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

It’s possible to support additional variable-types with a custom JSON representation (either simple value or complex/nested JSON object). By extending the initializeVariableConverters() method on org.flowable.dmn.rest.service.api.DmnRestResponseFactory, you can add additional org.flowable.rest.variable.RestVariableConverter classes to support converting your POJOs to a format suitable for transferring through REST and converting the REST-value back to your POJO. The actual transformation to JSON is done by Jackson.

## Deployment

**When using Tomcat, please read [Usage in Tomcat](#usage-In-tomcat).**

### List of Deployments

    GET repository/deployments

<table>
<caption>URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given name.</p></td>
</tr>
<tr class="even">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a name like the given name.</p></td>
</tr>
<tr class="odd">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given category.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns deployments without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'id' (default), 'name', 'deployTime' or 'tenantId'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>REST Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the request was successful.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id": "10",
          "name": "flowable-examples.bar",
          "deploymentTime": "2010-10-13T14:54:26.750+02:00",
          "category": "examples",
          "url": "http://localhost:8081/flowable-rest/service/repository/deployments/10",
          "tenantId": null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "id",
      "order": "asc",
      "size": 1
    }

### Get a deployment

    GET repository/deployments/{deploymentId}

<table>
<caption>Get a deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the deployment to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the deployment was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "10",
      "name": "flowable-examples.bar",
      "deploymentTime": "2010-10-13T14:54:26.750+02:00",
      "category": "examples",
      "url": "http://localhost:8081/flowable-rest/service/repository/deployments/10",
      "tenantId" : null
    }

### Create a new deployment

    POST repository/deployments

**Request body:**

The request body should contain data of type *multipart/form-data*. There should be exactly one file in the request, any additional files will be ignored. The deployment name is the name of the file-field passed in. If multiple resources need to be deployed in a single deployment, compress the resources in a zip and make sure the file-name ends with .bar or .zip.

An additional parameter (form-field) can be passed in the request body with name tenantId. The value of this field will be used as the id of the tenant this deployment is done in.

<table>
<caption>Create a new deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the deployment was created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates there was no content present in the request body or the content mime-type is not supported for deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "10",
      "name": "flowable-examples.bar",
      "deploymentTime": "2010-10-13T14:54:26.750+02:00",
      "category": null,
      "url": "http://localhost:8081/flowable-rest/service/repository/deployments/10",
      "tenantId" : "myTenant"
    }

### Delete a deployment

    DELETE repository/deployments/{deploymentId}

<table>
<caption>Delete a deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the deployment to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the deployment was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

### List resources in a deployment

    GET repository/deployments/{deploymentId}/resources

<table>
<caption>List resources in a deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the deployment to get the resources for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List resources in a deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the deployment was found and the resource list has been returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "id": "diagrams/my-process.bpmn20.xml",
        "url": "http://localhost:8081/flowable-rest/service/repository/deployments/10/resources/diagrams%2Fmy-process.bpmn20.xml",
        "dataUrl": "http://localhost:8081/flowable-rest/service/repository/deployments/10/resourcedata/diagrams%2Fmy-process.bpmn20.xml",
        "mediaType": "text/xml",
        "type": "processDefinition"
      },
      {
        "id": "image.png",
        "url": "http://localhost:8081/flowable-rest/service/repository/deployments/10/resources/image.png",
        "dataUrl": "http://localhost:8081/flowable-rest/service/repository/deployments/10/resourcedata/image.png",
        "mediaType": "image/png",
        "type": "resource"
      }
    ]

-   mediaType: Contains the media-type the resource has. This is resolved using a (pluggable) MediaTypeResolver and contains, by default, a limited number of mime-type mappings.

-   type: Type of resource, possible values:

-   resource: Plain old resource.

-   processDefinition: Resource that contains one or more process-definitions. This resource is picked up by the deployer.

-   processImage: Resource that represents a deployed process definition’s graphical layout.

*The dataUrl property in the resulting JSON for a single resource contains the actual URL to use for retrieving the binary resource.*

### Get a deployment resource

    GET repository/deployments/{deploymentId}/resources/{resourceId}

<table>
<caption>Get a deployment resource - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the deployment the requested resource is part of.</p></td>
</tr>
<tr class="even">
<td><p>resourceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the resource to get. <strong>Make sure you URL-encode the resourceId in case it contains forward slashes. Eg: use 'diagrams%2Fmy-process.bpmn20.xml' instead of 'diagrams/Fmy-process.bpmn20.xml'.</strong></p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a deployment resource - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both deployment and resource have been found and the resource has been returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found or there is no resource with the given id present in the deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "diagrams/my-process.bpmn20.xml",
      "url": "http://localhost:8081/flowable-rest/service/repository/deployments/10/resources/diagrams%2Fmy-process.bpmn20.xml",
      "dataUrl": "http://localhost:8081/flowable-rest/service/repository/deployments/10/resourcedata/diagrams%2Fmy-process.bpmn20.xml",
      "mediaType": "text/xml",
      "type": "processDefinition"
    }

-   mediaType: Contains the media-type the resource has. This is resolved using a (pluggable) MediaTypeResolver and contains, by default, a limited number of mime-type mappings.

-   type: Type of resource, possible values:

-   resource: Plain old resource.

-   processDefinition: Resource that contains one or more process-definitions. This resource is picked up by the deployer.

-   processImage: Resource that represents a deployed process definition’s graphical layout.

### Get a deployment resource content

    GET repository/deployments/{deploymentId}/resourcedata/{resourceId}

<table>
<caption>Get a deployment resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the deployment the requested resource is part of.</p></td>
</tr>
<tr class="even">
<td><p>resourceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the resource to get the data for. <strong>Make sure you URL-encode the resourceId in case it contains forward slashes. Eg: use 'diagrams%2Fmy-process.bpmn20.xml' instead of 'diagrams/Fmy-process.bpmn20.xml'.</strong></p></td>
</tr>
</tbody>
</table>

    .Get a deployment resource content - Response codes

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both deployment and resource have been found and the resource data has been returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found or there is no resource with the given id present in the deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body will contain the binary resource-content for the requested resource. The response content-type will be the same as the type returned in the resources 'mimeType' property. Also, a content-disposition header is set, allowing browsers to download the file instead of displaying it.

## Process Definitions

### List of process definitions

    GET repository/process-definitions

<table>
<caption>List of process definitions - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>version</p></td>
<td><p>No</p></td>
<td><p>integer</p></td>
<td><p>Only return process definitions with the given version.</p></td>
</tr>
<tr class="even">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given name.</p></td>
</tr>
<tr class="odd">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a name like the given name.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given key.</p></td>
</tr>
<tr class="odd">
<td><p>keyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a name like the given key.</p></td>
</tr>
<tr class="even">
<td><p>resourceName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given resource name.</p></td>
</tr>
<tr class="odd">
<td><p>resourceNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a name like the given resource name.</p></td>
</tr>
<tr class="even">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given category.</p></td>
</tr>
<tr class="odd">
<td><p>categoryLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a category like the given name.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions which are part of a deployment with the given id.</p></td>
</tr>
<tr class="even">
<td><p>startableByUser</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions which can be started by the given user.</p></td>
</tr>
<tr class="odd">
<td><p>latest</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Only return the latest process definition versions. Can only be used together with 'key', 'keyLike', 'resourceName' and 'resourceNameLike' parameters, using any other parameter will result in a 400-response.</p></td>
</tr>
<tr class="even">
<td><p>suspended</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns process definitions which are suspended. If false, only active process definitions (which are not suspended) are returned.</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'name' (default), 'id', 'key', 'category', 'deploymentId' and 'version'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of process definitions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the process-definitions are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format or that 'latest' is used with other parameters other than 'key' and 'keyLike'. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "oneTaskProcess:1:4",
          "url" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "version" : 1,
          "key" : "oneTaskProcess",
          "category" : "Examples",
          "suspended" : false,
          "name" : "The One Task Process",
          "description" : "This is a process for testing purposes",
          "deploymentId" : "2",
          "deploymentUrl" : "http://localhost:8081/repository/deployments/2",
          "graphicalNotationDefined" : true,
          "resource" : "http://localhost:8182/repository/deployments/2/resources/testProcess.xml",
          "diagramResource" : "http://localhost:8182/repository/deployments/2/resources/testProcess.png",
          "startFormDefined" : false
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

-   graphicalNotationDefined: Indicates the process definition contains graphical information (BPMN DI).

-   resource: Contains the actual deployed BPMN 2.0 xml.

-   diagramResource: Contains a graphical representation of the process, null when no diagram is available.

### Get a process definition

    GET repository/process-definitions/{processDefinitionId}

<table>
<caption>Get a process definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process definition was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id" : "oneTaskProcess:1:4",
      "url" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
      "version" : 1,
      "key" : "oneTaskProcess",
      "category" : "Examples",
      "suspended" : false,
      "name" : "The One Task Process",
      "description" : "This is a process for testing purposes",
      "deploymentId" : "2",
      "deploymentUrl" : "http://localhost:8081/repository/deployments/2",
      "graphicalNotationDefined" : true,
      "resource" : "http://localhost:8182/repository/deployments/2/resources/testProcess.xml",
      "diagramResource" : "http://localhost:8182/repository/deployments/2/resources/testProcess.png",
      "startFormDefined" : false
    }

-   graphicalNotationDefined: Indicates the process definition contains graphical information (BPMN DI).

-   resource: Contains the actual deployed BPMN 2.0 xml.

-   diagramResource: Contains a graphical representation of the process, null when no diagram is available.

### Update category for a process definition

    PUT repository/process-definitions/{processDefinitionId}

**Body JSON:**

    {
      "category" : "updatedcategory"
    }

<table>
<caption>Update category for a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process was category was altered.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates no category was defined in the request body.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for repository/process-definitions/{processDefinitionId}.

### Get a process definition resource content

    GET repository/process-definitions/{processDefinitionId}/resourcedata

<table>
<caption>Get a process definition resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition to get the resource data for.</p></td>
</tr>
</tbody>
</table>

**Response:**

Exactly the same response codes/boy as GET repository/deployment/{deploymentId}/resourcedata/{resourceId}.

### Get a process definition BPMN model

    GET repository/process-definitions/{processDefinitionId}/model

<table>
<caption>Get a process definition BPMN model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition to get the model for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a process definition BPMN model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process definition was found and the model is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
</tbody>
</table>

**Response body:**
The response body is a JSON representation of the org.flowable.bpmn.model.BpmnModel and contains the full process definition model.

    {
       "processes":[
          {
             "id":"oneTaskProcess",
             "xmlRowNumber":7,
             "xmlColumnNumber":60,
             "extensionElements":{

             },
             "name":"The One Task Process",
             "executable":true,
             "documentation":"One task process description",

        ]
    }

### Suspend a process definition

    PUT repository/process-definitions/{processDefinitionId}

**Body JSON:**

    {
      "action" : "suspend",
      "includeProcessInstances" : "false",
      "date" : "2013-04-15T00:42:12Z"
    }

<table>
<caption>Suspend a process definition - JSON Body parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>action</p></td>
<td><p>Action to perform. Either activate or suspend.</p></td>
<td><p>Yes</p></td>
</tr>
<tr class="even">
<td><p>includeProcessInstances</p></td>
<td><p>Whether or not to suspend/activate running process-instances for this process-definition. If omitted, the process-instances are left in the state they are.</p></td>
<td><p>No</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Date (ISO-8601) when the suspension/activation should be executed. If omitted, the suspend/activation is effective immediately.</p></td>
<td><p>No</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Suspend a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process was suspended.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
<tr class="odd">
<td><p>409</p></td>
<td><p>Indicates the requested process definition is already suspended.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for repository/process-definitions/{processDefinitionId}.

### Activate a process definition

    PUT repository/process-definitions/{processDefinitionId}

**Body JSON:**

    {
      "action" : "activate",
      "includeProcessInstances" : "true",
      "date" : "2013-04-15T00:42:12Z"
    }

See suspend process definition [JSON Body parameters](#json-body-parameters).

<table>
<caption>Activate a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process was activated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
<tr class="odd">
<td><p>409</p></td>
<td><p>Indicates the requested process definition is already active.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for repository/process-definitions/{processDefinitionId}.

### Get all candidate starters for a process-definition

    GET repository/process-definitions/{processDefinitionId}/identitylinks

<table>
<caption>Get all candidate starters for a process-definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition to get the identity links for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get all candidate starters for a process-definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process definition was found and the requested identity links are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "url":"http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4/identitylinks/groups/admin",
          "user":null,
          "group":"admin",
          "type":"candidate"
       },
       {
          "url":"http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4/identitylinks/users/kermit",
          "user":"kermit",
          "group":null,
          "type":"candidate"
       }
    ]

### Add a candidate starter to a process definition

    POST repository/process-definitions/{processDefinitionId}/identitylinks

<table>
<caption>Add a candidate starter to a process definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition.</p></td>
</tr>
</tbody>
</table>

**Request body (user):**

    {
      "user" : "kermit"
    }

**Request body (group):**

    {
      "groupId" : "sales"
    }

<table>
<caption>Add a candidate starter to a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the process definition was found and the identity link was created.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "url":"http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4/identitylinks/users/kermit",
      "user":"kermit",
      "group":null,
      "type":"candidate"
    }

### Delete a candidate starter from a process definition

    DELETE repository/process-definitions/{processDefinitionId}/identitylinks/{family}/{identityId}

<table>
<caption>Delete a candidate starter from a process definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition.</p></td>
</tr>
<tr class="even">
<td><p>family</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Either users or groups, depending on the type of identity link.</p></td>
</tr>
<tr class="odd">
<td><p>identityId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Either the userId or groupId of the identity to remove as candidate starter.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a candidate starter from a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the process definition was found and the identity link was removed. The response body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found or the process definition doesn’t have an identity-link that matches the url.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "url":"http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4/identitylinks/users/kermit",
      "user":"kermit",
      "group":null,
      "type":"candidate"
    }

### Get a candidate starter from a process definition

    GET repository/process-definitions/{processDefinitionId}/identitylinks/{family}/{identityId}

<table>
<caption>Get a candidate starter from a process definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process definition.</p></td>
</tr>
<tr class="even">
<td><p>family</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Either users or groups, depending on the type of identity link.</p></td>
</tr>
<tr class="odd">
<td><p>identityId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Either the userId or groupId of the identity to get as candidate starter.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a candidate starter from a process definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process definition was found and the identity link was returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process definition was not found or the process definition doesn’t have an identity-link that matches the url.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "url":"http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4/identitylinks/users/kermit",
      "user":"kermit",
      "group":null,
      "type":"candidate"
    }

## Models

### Get a list of models

    GET repository/models

<table>
<caption>Get a list of models - URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with the given id.</p></td>
</tr>
<tr class="even">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with the given category.</p></td>
</tr>
<tr class="odd">
<td><p>categoryLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with a category like the given value. Use the % character as wildcard.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models without the given category.</p></td>
</tr>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with the given name.</p></td>
</tr>
<tr class="even">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with a name like the given value. Use the % character as wildcard.</p></td>
</tr>
<tr class="odd">
<td><p>key</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with the given key.</p></td>
</tr>
<tr class="even">
<td><p>deploymentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models which are deployed in the given deployment.</p></td>
</tr>
<tr class="odd">
<td><p>version</p></td>
<td><p>No</p></td>
<td><p>Integer</p></td>
<td><p>Only return models with the given version.</p></td>
</tr>
<tr class="even">
<td><p>latestVersion</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only return models which are the latest version. Best used in combination with key. If false is passed in as value, this is ignored and all versions are returned.</p></td>
</tr>
<tr class="odd">
<td><p>deployed</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only deployed models are returned. If false, only undeployed models are returned (deploymentId is null).</p></td>
</tr>
<tr class="even">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with the given tenantId.</p></td>
</tr>
<tr class="odd">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return models with a tenantId like the given value.</p></td>
</tr>
<tr class="even">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns models without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'id' (default), 'category', 'createTime', 'key', 'lastUpdateTime', 'name', 'version' or 'tenantId'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a list of models - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the models are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "name":"Model name",
             "key":"Model key",
             "category":"Model category",
             "version":2,
             "metaInfo":"Model metainfo",
             "deploymentId":"7",
             "id":"10",
             "url":"http://localhost:8182/repository/models/10",
             "createTime":"2013-06-12T14:31:08.612+0000",
             "lastUpdateTime":"2013-06-12T14:31:08.612+0000",
             "deploymentUrl":"http://localhost:8182/repository/deployments/7",
             "tenantId":null
          },

          ...

       ],
       "total":2,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":2
    }

### Get a model

    GET repository/models/{modelId}

<table>
<caption>Get a model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>modelId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the model to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the model was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"5",
       "url":"http://localhost:8182/repository/models/5",
       "name":"Model name",
       "key":"Model key",
       "category":"Model category",
       "version":2,
       "metaInfo":"Model metainfo",
       "deploymentId":"2",
       "deploymentUrl":"http://localhost:8182/repository/deployments/2",
       "createTime":"2013-06-12T12:31:19.861+0000",
       "lastUpdateTime":"2013-06-12T12:31:19.861+0000",
       "tenantId":null
    }

### Update a model

    PUT repository/models/{modelId}

**Request body:**

    {
       "name":"Model name",
       "key":"Model key",
       "category":"Model category",
       "version":2,
       "metaInfo":"Model metainfo",
       "deploymentId":"2",
       "tenantId":"updatedTenant"
    }

All request values are optional. For example, you can only include the 'name' attribute in the request body JSON-object, only updating the name of the model, leaving all other fields unaffected. When an attribute is explicitly included and is set to null, the model-value will be updated to null. Example: {"metaInfo" : null} will clear the metaInfo of the model).

<table>
<caption>Update a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the model was found and updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"5",
       "url":"http://localhost:8182/repository/models/5",
       "name":"Model name",
       "key":"Model key",
       "category":"Model category",
       "version":2,
       "metaInfo":"Model metainfo",
       "deploymentId":"2",
       "deploymentUrl":"http://localhost:8182/repository/deployments/2",
       "createTime":"2013-06-12T12:31:19.861+0000",
       "lastUpdateTime":"2013-06-12T12:31:19.861+0000",
       "tenantId":""updatedTenant"
    }

### Create a model

    POST repository/models

**Request body:**

    {
       "name":"Model name",
       "key":"Model key",
       "category":"Model category",
       "version":1,
       "metaInfo":"Model metainfo",
       "deploymentId":"2",
       "tenantId":"tenant"
    }

All request values are optional. For example, you can only include the 'name' attribute in the request body JSON-object, only setting the name of the model, leaving all other fields null.

<table>
<caption>Create a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the model was created.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"5",
       "url":"http://localhost:8182/repository/models/5",
       "name":"Model name",
       "key":"Model key",
       "category":"Model category",
       "version":1,
       "metaInfo":"Model metainfo",
       "deploymentId":"2",
       "deploymentUrl":"http://localhost:8182/repository/deployments/2",
       "createTime":"2013-06-12T12:31:19.861+0000",
       "lastUpdateTime":"2013-06-12T12:31:19.861+0000",
       "tenantId":"tenant"
    }

### Delete a model

    DELETE repository/models/{modelId}

<table>
<caption>Delete a model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>modelId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the model to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the model was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

### Get the editor source for a model

    GET repository/models/{modelId}/source

<table>
<caption>Get the editor source for a model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>modelId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the model.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get the editor source for a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the model was found and source is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

Response body contains the model’s raw editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the source.

### Set the editor source for a model

    PUT repository/models/{modelId}/source

<table>
<caption>Set the editor source for a model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>modelId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the model.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the source.

<table>
<caption>Set the editor source for a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the model was found and the source has been updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

Response body contains the model’s raw editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the source.

### Get the extra editor source for a model

    GET repository/models/{modelId}/source-extra

<table>
<caption>Get the extra editor source for a model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>modelId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the model.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get the extra editor source for a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the model was found and source is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

Response body contains the model’s raw extra editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the extra source.

### Set the extra editor source for a model

    PUT repository/models/{modelId}/source-extra

<table>
<caption>Set the extra editor source for a model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>modelId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the model.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the extra source.

<table>
<caption>Set the extra editor source for a model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the model was found and the extra source has been updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested model was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

Response body contains the model’s raw editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the source.

## Process Instances

### Get a process instance

    GET runtime/process-instances/{processInstanceId}

<table>
<caption>Get a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"7",
       "url":"http://localhost:8182/runtime/process-instances/7",
       "businessKey":"myBusinessKey",
       "suspended":false,
       "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/processOne%3A1%3A4",
       "activityId":"processTask",
       "tenantId": null
    }

### Delete a process instance

    DELETE runtime/process-instances/{processInstanceId}?deleteReason={deleteReason}

<table>
<caption>Delete a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to delete.</p></td>
</tr>
<tr class="even">
<td><p>deleteReason</p></td>
<td><p>False</p></td>
<td><p>String</p></td>
<td><p>Reason why the process instance is deleted.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the process instance was found and deleted. Response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
</tbody>
</table>

### Activate or suspend a process instance

    PUT runtime/process-instances/{processInstanceId}

<table>
<caption>Activate or suspend a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to activate/suspend.</p></td>
</tr>
</tbody>
</table>

**Request response body (suspend):**

    {
       "action":"suspend"
    }

**Request response body (activate):**

    {
       "action":"activate"
    }

<table>
<caption>Activate or suspend a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and action was executed.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an invalid action was supplied.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the requested process instance action cannot be executed since the process-instance is already activated/suspended.</p></td>
</tr>
</tbody>
</table>

### Start a process instance

    POST runtime/process-instances

**Request body (start by process definition id):**

    {
       "processDefinitionId":"oneTaskProcess:1:158",
       "businessKey":"myBusinessKey",
       "returnVariables":true,
       "variables": [
          {
            "name":"myVar",
            "value":"This is a variable"
          }
       ]
    }

**Request body (start by process definition key):**

    {
       "processDefinitionKey":"oneTaskProcess",
       "businessKey":"myBusinessKey",
       "returnVariables":false,
       "tenantId": "tenant1",
       "variables": [
          {
            "name":"myVar",
            "value":"This is a variable"
          }
       ]
    }

**Request body (start by message):**

    {
       "message":"newOrderMessage",
       "businessKey":"myBusinessKey",
       "tenantId": "tenant1",
       "variables": [
          {
            "name":"myVar",
            "value":"This is a variable"
          }
       ]
    }

Note that also a *transientVariables* property is accepted as part of this json, that follows the same structure as the *variables* property.

The *returnVariables* property can be used to get the existing variables in the process instance context back in the response. By default the variables are not returned.

Only one of processDefinitionId, processDefinitionKey or message can be used in the request body. Parameters businessKey, variables and tenantId are optional. If tenantId is omitted, the default tenant will be used. More information about the variable format can be found in [the REST variables section](#variable-representation). Note that the variable-scope that is supplied is ignored, process-variables are always local.

<table>
<caption>Start a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the process instance was created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates either the process-definition was not found (based on id or key), no process is started by sending the given message or an invalid variable has been passed. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"7",
       "url":"http://localhost:8182/runtime/process-instances/7",
       "businessKey":"myBusinessKey",
       "suspended":false,
       "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/processOne%3A1%3A4",
       "activityId":"processTask",
       "tenantId" : null
    }

### List of process instances

    GET runtime/process-instances

<table>
<caption>List of process instances - URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instance with the given id.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances with the given process definition key.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances with the given process definition id.</p></td>
</tr>
<tr class="even">
<td><p>businessKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances with the given businessKey.</p></td>
</tr>
<tr class="odd">
<td><p>involvedUser</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances in which the given user is involved.</p></td>
</tr>
<tr class="even">
<td><p>suspended</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only return process instance which are suspended. If false, only return process instances which are not suspended (active).</p></td>
</tr>
<tr class="odd">
<td><p>superProcessInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances which have the given super process-instance id (for processes that have a call-activities).</p></td>
</tr>
<tr class="even">
<td><p>subProcessInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances which have the given sub process-instance id (for processes started as a call-activity).</p></td>
</tr>
<tr class="odd">
<td><p>excludeSubprocesses</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Return only process instances which aren’t sub processes.</p></td>
</tr>
<tr class="even">
<td><p>includeProcessVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication to include process variables in the result.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process instances with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns process instances without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Sort field, should be either one of id (default), processDefinitionId, tenantId or processDefinitionKey.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of process instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the process-instances are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format . The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"7",
             "url":"http://localhost:8182/runtime/process-instances/7",
             "businessKey":"myBusinessKey",
             "suspended":false,
             "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/processOne%3A1%3A4",
             "activityId":"processTask",
             "tenantId" : null
          }


       ],
       "total":2,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":2
    }

### Query process instances

    POST query/process-instances

**Request body:**

    {
      "processDefinitionKey":"oneTaskProcess",
      "variables":
      [
        {
            "name" : "myVariable",
            "value" : 1234,
            "operation" : "equals",
            "type" : "long"
        }
      ]
    }

The request body can contain all possible filters that can be used in the [List process instances](bpmn/ch14-REST.md#list-of-process-instances) URL query. On top of these, it’s possible to provide an array of variables
to include in the query, with their format [described here](#json-query-variable-format).

The general [paging and sorting query-parameters](#paging-and-sorting) can be used for this URL.

<table>
<caption>Query process instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the process-instances are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format . The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"7",
             "url":"http://localhost:8182/runtime/process-instances/7",
             "businessKey":"myBusinessKey",
             "suspended":false,
             "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/processOne%3A1%3A4",
             "activityId":"processTask",
             "tenantId" : null
          }


       ],
       "total":2,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":2
    }

### Get diagram for a process instance

    GET runtime/process-instances/{processInstanceId}/diagram

<table>
<caption>Get diagram for a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to get the diagram for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get diagram for a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and the diagram was returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the requested process instance was not found but the process doesn’t contain any graphical information (BPMN:DI) and no diagram can be created.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    The response is a Blob object containing the binary data or null.
    

### Get involved people for process instance

    GET runtime/process-instances/{processInstanceId}/identitylinks

<table>
<caption>Get involved people for process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to the links for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get involved people for process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and links are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "url":"http://localhost:8182/runtime/process-instances/5/identitylinks/users/john/customType",
          "user":"john",
          "group":null,
          "type":"customType"
       },
       {
          "url":"http://localhost:8182/runtime/process-instances/5/identitylinks/users/paul/candidate",
          "user":"paul",
          "group":null,
          "type":"candidate"
       }
    ]

Note that the groupId will always be null, as it’s only possible to involve users with a process-instance.

### Add an involved user to a process instance

    POST runtime/process-instances/{processInstanceId}/identitylinks

<table>
<caption>Add an involved user to a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to the links for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

    {
      "userId":"kermit",
      "type":"participant"
    }

Both userId and type are required.

<table>
<caption>Add an involved user to a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the process instance was found and the link is created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the requested body did not contain a userId or a type.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "url":"http://localhost:8182/runtime/process-instances/5/identitylinks/users/john/customType",
       "user":"john",
       "group":null,
       "type":"customType"
    }

Note that the groupId will always be null, as it’s only possible to involve users with a process-instance.

### Remove an involved user to from process instance

    DELETE runtime/process-instances/{processInstanceId}/identitylinks/users/{userId}/{type}

<table>
<caption>Remove an involved user to from process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance.</p></td>
</tr>
<tr class="even">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to delete link for.</p></td>
</tr>
<tr class="odd">
<td><p>type</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Type of link to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Remove an involved user to from process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the process instance was found and the link has been deleted. Response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found or the link to delete doesn’t exist. The response status contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "url":"http://localhost:8182/runtime/process-instances/5/identitylinks/users/john/customType",
       "user":"john",
       "group":null,
       "type":"customType"
    }

Note that the groupId will always be null, as it’s only possible to involve users with a process-instance.

### List of variables for a process instance

    GET runtime/process-instances/{processInstanceId}/variables

<table>
<caption>List of variables for a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to the variables for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of variables for a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and variables are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"local"
       },
       {
          "name":"byteArrayProcVar",
          "type":"binary",
          "value":null,
          "valueUrl":"http://localhost:8182/runtime/process-instances/5/variables/byteArrayProcVar/data",
          "scope":"local"
       }
    ]

In case the variable is a binary variable or serializable, the valueUrl points to an URL to fetch the raw value. If it’s a plain variable, the value is present in the response.
Note that only local scoped variables are returned, as there is no global scope for process-instance variables.

### Get a variable for a process instance

    GET runtime/process-instances/{processInstanceId}/variables/{variableName}

<table>
<caption>Get a variable for a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to the variables for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Name of the variable to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a variable for a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both the process instance and variable were found and variable is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the request body is incomplete or contains illegal values. The status description contains additional information about the error.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found or the process instance does not have a variable with the given name. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"local"
       }

In case the variable is a binary variable or serializable, the valueUrl points to an URL to fetch the raw value. If it’s a plain variable, the value is present in the response. Note that only local scoped variables are returned, as there is no global scope for process-instance variables.

### Create (or update) variables on a process instance

    POST runtime/process-instances/{processInstanceId}/variables

    PUT runtime/process-instances/{processInstanceId}/variables

When using POST, all variables that are passed are created. In case one of the variables already exists on the process instance, the request results in an error (409 - CONFLICT). When PUT is used, nonexistent variables are created on the process-instance and existing ones are overridden without any error.

<table>
<caption>Create (or update) variables on a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to the variables for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

    [
       {
          "name":"intProcVar",
          "type":"integer",
          "value":123
       },

       ...
    ]

Any number of variables can be passed into the request body array. More information about the variable format can be found in [the REST variables section](#variable-representation). Note that scope is ignored, only local variables can be set in a process instance.

<table>
<caption>Create (or update) variables on a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the process instance was found and variable is created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the request body is incomplete or contains illegal values. The status description contains additional information about the error.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the process instance was found but already contains a variable with the given name (only thrown when POST method is used). Use the update-method instead.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"local"
       },

       ...

    ]

### Update a single variable on a process instance

    PUT runtime/process-instances/{processInstanceId}/variables/{variableName}

<table>
<caption>Update a single variable on a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to the variables for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Name of the variable to get.</p></td>
</tr>
</tbody>
</table>

**Request body:**

     {
        "name":"intProcVar"
        "type":"integer"
        "value":123
     }

More information about the variable format can be found in [the REST variables section](#variable-representation). Note that scope is ignored, only local variables can be set in a process instance.

<table>
<caption>Update a single variable on a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both the process instance and variable were found and variable is updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found or the process instance does not have a variable with the given name. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "name":"intProcVar",
      "type":"integer",
      "value":123,
      "scope":"local"
    }

In case the variable is a binary variable or serializable, the valueUrl points to an URL to fetch the raw value. If it’s a plain variable, the value is present in the response. Note that only local scoped variables are returned, as there is no global scope for process-instance variables.

### Create a new binary variable on a process-instance

    POST runtime/process-instances/{processInstanceId}/variables

<table>
<caption>Create a new binary variable on a process-instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to create the new variable for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   type: Type of variable that is created. If omitted, binary is assumed and the binary data in the request will be stored as an array of bytes.

**Success response body:**

    {
      "name" : "binaryVariable",
      "scope" : "local",
      "type" : "binary",
      "value" : null,
      "valueUrl" : "http://.../runtime/process-instances/123/variables/binaryVariable/data"
    }

<table>
<caption>Create a new binary variable on a process-instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the variable was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of the variable to create was missing. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the process instance already has a variable with the given name. Use the PUT method to update the task variable instead.</p></td>
</tr>
<tr class="odd">
<td><p>415</p></td>
<td><p>Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.</p></td>
</tr>
</tbody>
</table>

### Update an existing binary variable on a process-instance

    PUT runtime/process-instances/{processInstanceId}/variables

<table>
<caption>Update an existing binary variable on a process-instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to create the new variable for.</p></td>
</tr>
</tbody>
</table>

**Request body:**
The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   type: Type of variable that is created. If omitted, binary is assumed and the binary data in the request will be stored as an array of bytes.

**Success response body:**

    {
      "name" : "binaryVariable",
      "scope" : "local",
      "type" : "binary",
      "value" : null,
      "valueUrl" : "http://.../runtime/process-instances/123/variables/binaryVariable/data"
    }

<table>
<caption>Update an existing binary variable on a process-instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the variable was updated and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of the variable to update was missing. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found or the process instance does not have a variable with the given name.</p></td>
</tr>
<tr class="even">
<td><p>415</p></td>
<td><p>Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.</p></td>
</tr>
</tbody>
</table>

## Executions

### Get an execution

    GET runtime/executions/{executionId}

<table>
<caption>Get an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the execution was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the execution was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"5",
       "url":"http://localhost:8182/runtime/executions/5",
       "parentId":null,
       "parentUrl":null,
       "processInstanceId":"5",
       "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
       "suspended":false,
       "activityId":null,
       "tenantId": null
    }

### Execute an action on an execution

    PUT runtime/executions/{executionId}

<table>
<caption>Execute an action on an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to execute action on.</p></td>
</tr>
</tbody>
</table>

**Request body (signal an execution):**

    {
      "action":"signal"
    }

Both a *variables* and *transientVariables* property is accepted with following structure:

    {
      "action":"signal",
      "variables" : [
        {
          "name": "myVar",
          "value": "someValue"
        }
      ]
    }

**Request body (signal event received for execution):**

    {
      "action":"signalEventReceived",
      "signalName":"mySignal"
      "variables": [  ]
    }

Notifies the execution that a signal event has been received, requires a signalName parameter. Optional variables can be passed that are set on the execution before the action is executed.

**Request body (signal event received for execution):**

    {
      "action":"messageEventReceived",
      "messageName":"myMessage"
      "variables": [  ]
    }

Notifies the execution that a message event has been received, requires a messageName parameter. Optional variables can be passed that are set on the execution before the action is executed.

<table>
<caption>Execute an action on an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the execution was found and the action is performed.</p></td>
</tr>
<tr class="even">
<td><p>204</p></td>
<td><p>Indicates the execution was found, the action was performed and the action caused the execution to end.</p></td>
</tr>
<tr class="odd">
<td><p>400</p></td>
<td><p>Indicates an illegal action was requested, required parameters are missing in the request body or illegal variables are passed in. Status description contains additional information about the error.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the execution was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body (in case execution is not ended due to action):**

    {
       "id":"5",
       "url":"http://localhost:8182/runtime/executions/5",
       "parentId":null,
       "parentUrl":null,
       "processInstanceId":"5",
       "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
       "suspended":false,
       "activityId":null,
       "tenantId" : null
    }

### Get active activities in an execution

    GET runtime/executions/{executionId}/activities

Returns all activities which are active in the execution and in all child-executions (and their children, recursively), if any.

<table>
<caption>Get active activities in an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to get activities for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get active activities in an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the execution was found and activities are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the execution was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      "userTaskForManager",
      "receiveTask"
    ]

### List of executions

    GET runtime/executions

<table>
<caption>List of executions - URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions with the given id.</p></td>
</tr>
<tr class="even">
<td><p>activityId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions with the given activity id.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions with the given process definition key.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions with the given process definition id.</p></td>
</tr>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions which are part of the process instance with the given id.</p></td>
</tr>
<tr class="even">
<td><p>messageEventSubscriptionName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions which are subscribed to a message with the given name.</p></td>
</tr>
<tr class="odd">
<td><p>signalEventSubscriptionName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions which are subscribed to a signal with the given name.</p></td>
</tr>
<tr class="even">
<td><p>parentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions which are a direct child of the given execution.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return executions with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns executions without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Sort field, should be either one of processInstanceId (default), processDefinitionId, processDefinitionKey or tenantId.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of executions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the executions are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format . The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"5",
             "url":"http://localhost:8182/runtime/executions/5",
             "parentId":null,
             "parentUrl":null,
             "processInstanceId":"5",
             "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
             "suspended":false,
             "activityId":null,
             "tenantId":null
          },
          {
             "id":"7",
             "url":"http://localhost:8182/runtime/executions/7",
             "parentId":"5",
             "parentUrl":"http://localhost:8182/runtime/executions/5",
             "processInstanceId":"5",
             "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
             "suspended":false,
             "activityId":"processTask",
             "tenantId":null
          }
       ],
       "total":2,
       "start":0,
       "sort":"processInstanceId",
       "order":"asc",
       "size":2
    }

### Query executions

    POST query/executions

**Request body:**

    {
      "processDefinitionKey":"oneTaskProcess",
      "variables":
      [
        {
            "name" : "myVariable",
            "value" : 1234,
            "operation" : "equals",
            "type" : "long"
        }
      ],
      "processInstanceVariables":
      [
        {
            "name" : "processVariable",
            "value" : "some string",
            "operation" : "equals",
            "type" : "string"
        }
      ]
    }

The request body can contain all possible filters that can be used in the [List executions](bpmn/ch14-REST.md#list-of-executions) URL query. On top of these, it’s possible to provide an array of variables and processInstanceVariables
to include in the query, with their format [described here](#json-query-variable-format).

The general [paging and sorting query-parameters](#paging-and-sorting) can be used for this URL.

<table>
<caption>Query executions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the executions are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format . The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"5",
             "url":"http://localhost:8182/runtime/executions/5",
             "parentId":null,
             "parentUrl":null,
             "processInstanceId":"5",
             "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
             "suspended":false,
             "activityId":null,
             "tenantId":null
          },
          {
             "id":"7",
             "url":"http://localhost:8182/runtime/executions/7",
             "parentId":"5",
             "parentUrl":"http://localhost:8182/runtime/executions/5",
             "processInstanceId":"5",
             "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
             "suspended":false,
             "activityId":"processTask",
             "tenantId":null
          }
       ],
       "total":2,
       "start":0,
       "sort":"processInstanceId",
       "order":"asc",
       "size":2
    }

### List of variables for an execution

    GET runtime/executions/{executionId}/variables?scope={scope}

<table>
<caption>List of variables for an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to the variables for.</p></td>
</tr>
<tr class="even">
<td><p>scope</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Either local or global. If omitted, both local and global scoped variables are returned.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of variables for an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the execution was found and variables are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested execution was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"global"
       },
       {
          "name":"byteArrayProcVar",
          "type":"binary",
          "value":null,
          "valueUrl":"http://localhost:8182/runtime/process-instances/5/variables/byteArrayProcVar/data",
          "scope":"local"
       }


    ]

In case the variable is a binary variable or serializable, the valueUrl points to an URL to fetch the raw value. If it’s a plain variable, the value is present in the response.

### Get a variable for an execution

    GET runtime/executions/{executionId}/variables/{variableName}?scope={scope}

<table>
<caption>Get a variable for an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to the variables for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Name of the variable to get.</p></td>
</tr>
<tr class="odd">
<td><p>scope</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Either local or global. If omitted, local variable is returned (if exists). If not, a global variable is returned (if exists).</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a variable for an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both the execution and variable were found and variable is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the request body is incomplete or contains illegal values. The status description contains additional information about the error.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested execution was not found or the execution does not have a variable with the given name in the requested scope (in case scope-query parameter was omitted, variable doesn’t exist in local and global scope). Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"local"
       }

In case the variable is a binary variable or serializable, the valueUrl points to an URL to fetch the raw value. If it’s a plain variable, the value is present in the response.

### Create (or update) variables on an execution

    POST runtime/executions/{executionId}/variables

    PUT runtime/executions/{executionId}/variables

When using POST, all variables that are passed are created. In case one of the variables already exists on the execution in the requested scope, the request results in an error (409 - CONFLICT). When PUT is used, nonexistent variables are created on the execution and existing ones are overridden without any error.

<table>
<caption>Create (or update) variables on an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to the variables for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

    [
       {
          "name":"intProcVar"
          "type":"integer"
          "value":123,
          "scope":"local"
       }



    ]

\*Note that you can only provide variables that have the same scope. If the request-body array contains variables from mixed scopes, the request results in an error (400 - BAD REQUEST).\*Any number of variables can be passed into the request body array. More information about the variable format can be found in [the REST variables section](#variable-representation). Note that scope is ignored, only local variables can be set in a process instance.

<table>
<caption>Create (or update) variables on an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the execution was found and variable is created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the request body is incomplete or contains illegal values. The status description contains additional information about the error.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested execution was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the execution was found but already contains a variable with the given name (only thrown when POST method is used). Use the update-method instead.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"local"
       }



    ]

### Update a variable on an execution

    PUT runtime/executions/{executionId}/variables/{variableName}

<table>
<caption>Update a variable on an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to update the variables for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Name of the variable to update.</p></td>
</tr>
</tbody>
</table>

**Request body:**

     {
        "name":"intProcVar"
        "type":"integer"
        "value":123,
        "scope":"global"
     }

More information about the variable format can be found in [the REST variables section](#variable-representation).

<table>
<caption>Update a variable on an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both the process instance and variable were found and variable is updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found or the process instance does not have a variable with the given name. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

       {
          "name":"intProcVar",
          "type":"integer",
          "value":123,
          "scope":"global"
       }

In case the variable is a binary variable or serializable, the valueUrl points to an URL to fetch the raw value. If it’s a plain variable, the value is present in the response.

### Create a new binary variable on an execution

    POST runtime/executions/{executionId}/variables

<table>
<caption>Create a new binary variable on an execution - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to create the new variable for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   type: Type of variable that is created. If omitted, binary is assumed and the binary data in the request will be stored as an array of bytes.

-   scope: Scope of variable that is created. If omitted, local is assumed.

**Success response body:**

    {
      "name" : "binaryVariable",
      "scope" : "local",
      "type" : "binary",
      "value" : null,
      "valueUrl" : "http://.../runtime/executions/123/variables/binaryVariable/data"
    }

<table>
<caption>Create a new binary variable on an execution - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the variable was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of the variable to create was missing. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested execution was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the execution already has a variable with the given name. Use the PUT method to update the task variable instead.</p></td>
</tr>
<tr class="odd">
<td><p>415</p></td>
<td><p>Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.</p></td>
</tr>
</tbody>
</table>

### Update an existing binary variable on a process-instance

    PUT runtime/executions/{executionId}/variables/{variableName}

<table>
<caption>Update an existing binary variable on a process-instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the execution to create the new variable for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the variable to update.</p></td>
</tr>
</tbody>
</table>

**Request body:**
The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   type: Type of variable that is created. If omitted, binary is assumed and the binary data in the request will be stored as an array of bytes.

-   scope: Scope of variable that is created. If omitted, local is assumed.

**Success response body:**

    {
      "name" : "binaryVariable",
      "scope" : "local",
      "type" : "binary",
      "value" : null,
      "valueUrl" : "http://.../runtime/executions/123/variables/binaryVariable/data"
    }

<table>
<caption>Update an existing binary variable on a process-instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the variable was updated and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of the variable to update was missing. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested execution was not found or the execution does not have a variable with the given name.</p></td>
</tr>
<tr class="even">
<td><p>415</p></td>
<td><p>Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.</p></td>
</tr>
</tbody>
</table>

## Tasks

### Get a task

    GET runtime/tasks/{taskId}

<table>
<caption>Get a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "assignee" : "kermit",
      "createTime" : "2013-04-17T10:17:43.902+0000",
      "delegationState" : "pending",
      "description" : "Task description",
      "dueDate" : "2013-04-17T10:17:43.902+0000",
      "execution" : "http://localhost:8182/runtime/executions/5",
      "id" : "8",
      "name" : "My task",
      "owner" : "owner",
      "parentTask" : "http://localhost:8182/runtime/tasks/9",
      "priority" : 50,
      "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
      "processInstanceUrl" : "http://localhost:8182/runtime/process-instances/5",
      "suspended" : false,
      "taskDefinitionKey" : "theTask",
      "url" : "http://localhost:8182/runtime/tasks/8",
      "tenantId" : null
    }

-   delegationState: Delegation-state of the task, can be null, "pending" or "resolved".

### List of tasks

    GET runtime/tasks

<table>
<caption>List of tasks - URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with the given name.</p></td>
</tr>
<tr class="even">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with a name like the given name.</p></td>
</tr>
<tr class="odd">
<td><p>description</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with the given description.</p></td>
</tr>
<tr class="even">
<td><p>priority</p></td>
<td><p>No</p></td>
<td><p>Integer</p></td>
<td><p>Only return tasks with the given priority.</p></td>
</tr>
<tr class="odd">
<td><p>minimumPriority</p></td>
<td><p>No</p></td>
<td><p>Integer</p></td>
<td><p>Only return tasks with a priority greater than the given value.</p></td>
</tr>
<tr class="even">
<td><p>maximumPriority</p></td>
<td><p>No</p></td>
<td><p>Integer</p></td>
<td><p>Only return tasks with a priority lower than the given value.</p></td>
</tr>
<tr class="odd">
<td><p>assignee</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks assigned to the given user.</p></td>
</tr>
<tr class="even">
<td><p>assigneeLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks assigned with an assignee like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>owner</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks owned by the given user.</p></td>
</tr>
<tr class="even">
<td><p>ownerLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks assigned with an owner like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>unassigned</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Only return tasks that are not assigned to anyone. If false is passed, the value is ignored.</p></td>
</tr>
<tr class="even">
<td><p>delegationState</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks that have the given delegation state. Possible values are pending and resolved.</p></td>
</tr>
<tr class="odd">
<td><p>candidateUser</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks that can be claimed by the given user. This includes both tasks where the user is an explicit candidate for and task that are claimable by a group that the user is a member of.</p></td>
</tr>
<tr class="even">
<td><p>candidateGroup</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks that can be claimed by a user in the given group.</p></td>
</tr>
<tr class="odd">
<td><p>candidateGroups</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks that can be claimed by a user in the given groups. Values split by comma.</p></td>
</tr>
<tr class="even">
<td><p>involvedUser</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks in which the given user is involved.</p></td>
</tr>
<tr class="odd">
<td><p>taskDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with the given task definition id.</p></td>
</tr>
<tr class="even">
<td><p>taskDefinitionKeyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with a given task definition id like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of the process instance with the given id.</p></td>
</tr>
<tr class="even">
<td><p>processInstanceBusinessKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of the process instance with the given business key.</p></td>
</tr>
<tr class="odd">
<td><p>processInstanceBusinessKeyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of the process instance which has a business key like the given value.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of a process instance which has a process definition with the given id.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of a process instance which has a process definition with the given key.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionKeyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of a process instance which has a process definition with a key like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of a process instance which has a process definition with the given name.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of a process instance which has a process definition with a name like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks which are part of the execution with the given id.</p></td>
</tr>
<tr class="even">
<td><p>createdOn</p></td>
<td><p>No</p></td>
<td><p>ISO Date</p></td>
<td><p>Only return tasks which are created on the given date.</p></td>
</tr>
<tr class="odd">
<td><p>createdBefore</p></td>
<td><p>No</p></td>
<td><p>ISO Date</p></td>
<td><p>Only return tasks which are created before the given date.</p></td>
</tr>
<tr class="even">
<td><p>createdAfter</p></td>
<td><p>No</p></td>
<td><p>ISO Date</p></td>
<td><p>Only return tasks which are created after the given date.</p></td>
</tr>
<tr class="odd">
<td><p>dueOn</p></td>
<td><p>No</p></td>
<td><p>ISO Date</p></td>
<td><p>Only return tasks which are due on the given date.</p></td>
</tr>
<tr class="even">
<td><p>dueBefore</p></td>
<td><p>No</p></td>
<td><p>ISO Date</p></td>
<td><p>Only return tasks which are due before the given date.</p></td>
</tr>
<tr class="odd">
<td><p>dueAfter</p></td>
<td><p>No</p></td>
<td><p>ISO Date</p></td>
<td><p>Only return tasks which are due after the given date.</p></td>
</tr>
<tr class="even">
<td><p>withoutDueDate</p></td>
<td><p>No</p></td>
<td><p>boolean</p></td>
<td><p>Only return tasks which don’t have a due date. The property is ignored if the value is false.</p></td>
</tr>
<tr class="odd">
<td><p>excludeSubTasks</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Only return tasks that are not a subtask of another task.</p></td>
</tr>
<tr class="even">
<td><p>active</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only return tasks that are not suspended (either part of a process that is not suspended or not part of a process at all). If false, only tasks that are part of suspended process instances are returned.</p></td>
</tr>
<tr class="odd">
<td><p>includeTaskLocalVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication to include task local variables in the result.</p></td>
</tr>
<tr class="even">
<td><p>includeProcessVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication to include process variables in the result.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return tasks with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns tasks without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>candidateOrAssigned</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Select tasks that has been claimed or assigned to user or waiting to claim by user (candidate user or groups).</p></td>
</tr>
<tr class="odd">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>string</p></td>
<td><p>Select tasks with the given category. Note that this is the task category, not the category of the process definition (namespace within the BPMN Xml).</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of tasks - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the tasks are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format or that 'delegationState' has an invalid value (other than 'pending' and 'resolved'). The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "assignee" : "kermit",
          "createTime" : "2013-04-17T10:17:43.902+0000",
          "delegationState" : "pending",
          "description" : "Task description",
          "dueDate" : "2013-04-17T10:17:43.902+0000",
          "execution" : "http://localhost:8182/runtime/executions/5",
          "id" : "8",
          "name" : "My task",
          "owner" : "owner",
          "parentTask" : "http://localhost:8182/runtime/tasks/9",
          "priority" : 50,
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "processInstanceUrl" : "http://localhost:8182/runtime/process-instances/5",
          "suspended" : false,
          "taskDefinitionKey" : "theTask",
          "url" : "http://localhost:8182/runtime/tasks/8",
          "tenantId" : null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Query for tasks

    POST query/tasks

**Request body:**

    {
      "name" : "My task",
      "description" : "The task description",

      ...

      "taskVariables" : [
        {
          "name" : "myVariable",
          "value" : 1234,
          "operation" : "equals",
          "type" : "long"
        }
      ],

        "processInstanceVariables" : [
          {
             ...
          }
        ]
      ]
    }

All supported JSON parameter fields allowed are exactly the same as the parameters found for [getting a collection of tasks](bpmn/ch14-REST.md#list-of-tasks) (except for candidateGroupIn which is only available in this POST task query REST service), but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri’s that are too long. On top of that, the query allows for filtering based on task and process variables. The taskVariables and processInstanceVariables are both JSON-arrays containing objects with the format [as described here.](#json-query-variable-format)

<table>
<caption>Query for tasks - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the tasks are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format or that 'delegationState' has an invalid value (other than 'pending' and 'resolved'). The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "assignee" : "kermit",
          "createTime" : "2013-04-17T10:17:43.902+0000",
          "delegationState" : "pending",
          "description" : "Task description",
          "dueDate" : "2013-04-17T10:17:43.902+0000",
          "execution" : "http://localhost:8182/runtime/executions/5",
          "id" : "8",
          "name" : "My task",
          "owner" : "owner",
          "parentTask" : "http://localhost:8182/runtime/tasks/9",
          "priority" : 50,
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "processInstanceUrl" : "http://localhost:8182/runtime/process-instances/5",
          "suspended" : false,
          "taskDefinitionKey" : "theTask",
          "url" : "http://localhost:8182/runtime/tasks/8",
          "tenantId" : null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Update a task

    PUT runtime/tasks/{taskId}

**Body JSON:**

    {
      "assignee" : "assignee",
      "delegationState" : "resolved",
      "description" : "New task description",
      "dueDate" : "2013-04-17T13:06:02.438+02:00",
      "name" : "New task name",
      "owner" : "owner",
      "parentTaskId" : "3",
      "priority" : 20
    }

All request values are optional. For example, you can only include the 'assignee' attribute in the request body JSON-object, only updating the assignee of the task, leaving all other fields unaffected. When an attribute is explicitly included and is set to null, the task-value will be updated to null. Example: {"dueDate" : null} will clear the duedate of the task).

<table>
<caption>Update a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
<tr class="odd">
<td><p>409</p></td>
<td><p>Indicates the requested task was updated simultaneously.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for runtime/tasks/{taskId}.

### Task actions

    POST runtime/tasks/{taskId}

**Complete a task - Body JSON:**

    {
      "action" : "complete",
      "variables" : []
    }

Completes the task. Optional variable array can be passed in using the variables property. More information about the variable format can be found in [the REST variables section](#variable-representation). Note that the variable-scope that is supplied is ignored and the variables are set on the parent-scope unless a variable exists in a local scope, which is overridden in this case. This is the same behavior as the TaskService.completeTask(taskId, variables) invocation.

Note that also a *transientVariables* property is accepted as part of this json, that follows the same structure as the *variables* property.

**Claim a task - Body JSON:**

    {
      "action" : "claim",
      "assignee" : "userWhoClaims"
    }

Claims the task by the given assignee. If the assignee is null, the task is assigned to no-one, claimable again.

**Delegate a task - Body JSON:**

    {
      "action" : "delegate",
      "assignee" : "userToDelegateTo"
    }

Delegates the task to the given assignee. The assignee is required.

**Resolve a task - Body JSON:**

    {
      "action" : "resolve"
    }

Resolves the task delegation. The task is assigned back to the task owner (if any).

<table>
<caption>Task actions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the action was executed.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>When the body contains an invalid value or when the assignee is missing when the action requires it.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the action cannot be performed due to a conflict. Either the task was updates simultaneously or the task was claimed by another user, in case of the 'claim' action.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for runtime/tasks/{taskId}.

### Delete a task

    DELETE runtime/tasks/{taskId}?cascadeHistory={cascadeHistory}&deleteReason={deleteReason}

<table>
<caption>Delete a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to delete.</p></td>
</tr>
<tr class="even">
<td><p>cascadeHistory</p></td>
<td><p>False</p></td>
<td><p>Boolean</p></td>
<td><p>Whether or not to delete the HistoricTask instance when deleting the task (if applicable). If not provided, this value defaults to false.</p></td>
</tr>
<tr class="odd">
<td><p>deleteReason</p></td>
<td><p>False</p></td>
<td><p>String</p></td>
<td><p>Reason why the task is deleted. This value is ignored when cascadeHistory is true.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the task was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>403</p></td>
<td><p>Indicates the requested task cannot be deleted because it’s part of a workflow.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get all variables for a task

    GET runtime/tasks/{taskId}/variables?scope={scope}

<table>
<caption>Get all variables for a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get variables for.</p></td>
</tr>
<tr class="even">
<td><p>scope</p></td>
<td><p>False</p></td>
<td><p>String</p></td>
<td><p>Scope of variables to be returned. When 'local', only task-local variables are returned. When 'global', only variables from the task’s parent execution-hierarchy are returned. When the parameter is omitted, both local and global variables are returned.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get all variables for a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the requested variables are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "name" : "doubleTaskVar",
        "scope" : "local",
        "type" : "double",
        "value" : 99.99
      },
      {
        "name" : "stringProcVar",
        "scope" : "global",
        "type" : "string",
        "value" : "This is a ProcVariable"
      }



    ]

The variables are returned as a JSON array. Full response description can be found in the general [REST-variables section](#variable-representation).

### Get a variable from a task

    GET runtime/tasks/{taskId}/variables/{variableName}?scope={scope}

<table>
<caption>Get a variable from a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get a variable for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the variable to get.</p></td>
</tr>
<tr class="odd">
<td><p>scope</p></td>
<td><p>False</p></td>
<td><p>String</p></td>
<td><p>Scope of variable to be returned. When 'local', only task-local variable value is returned. When 'global', only variable value from the task’s parent execution-hierarchy are returned. When the parameter is omitted, a local variable will be returned if it exists, otherwise a global variable.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a variable from a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the requested variables are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have a variable with the given name (in the given scope). Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "name" : "myTaskVariable",
      "scope" : "local",
      "type" : "string",
      "value" : "Hello my friend"
    }

Full response body description can be found in the general [REST-variables section](#variable-representation).

### Get the binary data for a variable

    GET runtime/tasks/{taskId}/variables/{variableName}/data?scope={scope}

<table>
<caption>Get the binary data for a variable - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get a variable data for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the variable to get data for. Only variables of type binary and serializable can be used. If any other type of variable is used, a 404 is returned.</p></td>
</tr>
<tr class="odd">
<td><p>scope</p></td>
<td><p>False</p></td>
<td><p>String</p></td>
<td><p>Scope of variable to be returned. When 'local', only task-local variable value is returned. When 'global', only variable value from the task’s parent execution-hierarchy are returned. When the parameter is omitted, a local variable will be returned if it exists, otherwise a global variable.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get the binary data for a variable - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the requested variables are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have a variable with the given name (in the given scope) or the variable doesn’t have a binary stream available. Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body contains the binary value of the variable. When the variable is of type binary, the content-type of the response is set to application/octet-stream, regardless of the content of the variable or the request accept-type header. In case of serializable, application/x-java-serialized-object is used as content-type.

### Create new variables on a task

    POST runtime/tasks/{taskId}/variables

<table>
<caption>Create new variables on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to create the new variable for.</p></td>
</tr>
</tbody>
</table>

**Request body for creating simple (non-binary) variables:**

    [
      {
        "name" : "myTaskVariable",
        "scope" : "local",
        "type" : "string",
        "value" : "Hello my friend"
      },
      {

      }
    ]

The request body should be an array containing one or more JSON-objects representing the variables that should be created.

-   name: Required name of the variable

-   scope: Scope of variable that is created. If omitted, local is assumed.

-   type: Type of variable that is created. If omitted, reverts to raw JSON-value type (string, boolean, integer or double).

-   value: Variable value.

More information about the variable format can be found in [the REST variables section](#variable-representation).

**Success response body:**

    [
      {
        "name" : "myTaskVariable",
        "scope" : "local",
        "type" : "string",
        "value" : "Hello my friend"
      },
      {

      }
    ]

<table>
<caption>Create new variables on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the variables were created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of a variable to create was missing or that an attempt is done to create a variable on a standalone task (without a process associated) with scope global or an empty array of variables was included in the request or request did not contain an array of variables. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the task already has a variable with the given name. Use the PUT method to update the task variable instead.</p></td>
</tr>
</tbody>
</table>

### Create a new binary variable on a task

    POST runtime/tasks/{taskId}/variables

<table>
<caption>Create a new binary variable on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to create the new variable for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   scope: Scope of variable that is created. If omitted, local is assumed.

-   type: Type of variable that is created. If omitted, binary is assumed and the binary data in the request will be stored as an array of bytes.

**Success response body:**

    {
      "name" : "binaryVariable",
      "scope" : "local",
      "type" : "binary",
      "value" : null,
      "valueUrl" : "http://.../runtime/tasks/123/variables/binaryVariable/data"
    }

<table>
<caption>Create a new binary variable on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the variable was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of the variable to create was missing or that an attempt is done to create a variable on a standalone task (without a process associated) with scope global. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the task already has a variable with the given name. Use the PUT method to update the task variable instead.</p></td>
</tr>
<tr class="odd">
<td><p>415</p></td>
<td><p>Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.</p></td>
</tr>
</tbody>
</table>

### Update an existing variable on a task

    PUT runtime/tasks/{taskId}/variables/{variableName}

<table>
<caption>Update an existing variable on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to update the variable for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the variable to update.</p></td>
</tr>
</tbody>
</table>

**Request body for updating simple (non-binary) variables:**

    {
      "name" : "myTaskVariable",
      "scope" : "local",
      "type" : "string",
      "value" : "Hello my friend"
    }

-   name: Required name of the variable

-   scope: Scope of variable that is updated. If omitted, local is assumed.

-   type: Type of variable that is updated. If omitted, reverts to raw JSON-value type (string, boolean, integer or double).

-   value: Variable value.

More information about the variable format can be found in [the REST variables section](#variable-representation).

**Success response body:**

    {
      "name" : "myTaskVariable",
      "scope" : "local",
      "type" : "string",
      "value" : "Hello my friend"
    }

<table>
<caption>Update an existing variable on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the variables was updated and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of a variable to update was missing or that an attempt is done to update a variable on a standalone task (without a process associated) with scope global. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have a variable with the given name in the given scope. Status message contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Updating a binary variable on a task

    PUT runtime/tasks/{taskId}/variables/{variableName}

<table>
<caption>Updating a binary variable on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to update the variable for.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the variable to update.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   scope: Scope of variable that is updated. If omitted, local is assumed.

-   type: Type of variable that is updated. If omitted, binary is assumed and the binary data in the request will be stored as an array of bytes.

**Success response body:**

    {
      "name" : "binaryVariable",
      "scope" : "local",
      "type" : "binary",
      "value" : null,
      "valueUrl" : "http://.../runtime/tasks/123/variables/binaryVariable/data"
    }

<table>
<caption>Updating a binary variable on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the variable was updated and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the name of the variable to update was missing or that an attempt is done to update a variable on a standalone task (without a process associated) with scope global. Status message provides additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the variable to update doesn’t exist for the given task in the given scope.</p></td>
</tr>
<tr class="even">
<td><p>415</p></td>
<td><p>Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.</p></td>
</tr>
</tbody>
</table>

### Delete a variable on a task

    DELETE runtime/tasks/{taskId}/variables/{variableName}?scope={scope}

<table>
<caption>Delete a variable on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task the variable to delete belongs to.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the variable to delete.</p></td>
</tr>
<tr class="odd">
<td><p>scope</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Scope of variable to delete in. Can be either local or global. If omitted, local is assumed.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a variable on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the task variable was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have a variable with the given name. Status message contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Delete all local variables on a task

    DELETE runtime/tasks/{taskId}/variables

<table>
<caption>Delete all local variables on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task the variable to delete belongs to.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete all local variables on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates all local task variables have been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get all identity links for a task

    GET runtime/tasks/{taskId}/identitylinks

<table>
<caption>Get all identity links for a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the identity links for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get all identity links for a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the requested identity links are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "userId" : "kermit",
        "groupId" : null,
        "type" : "candidate",
        "url" : "http://localhost:8081/flowable-rest/service/runtime/tasks/100/identitylinks/users/kermit/candidate"
      },
      {
        "userId" : null,
        "groupId" : "sales",
        "type" : "candidate",
        "url" : "http://localhost:8081/flowable-rest/service/runtime/tasks/100/identitylinks/groups/sales/candidate"
      },

      ...
    ]

### Get all identitylinks for a task for either groups or users

    GET runtime/tasks/{taskId}/identitylinks/users
    GET runtime/tasks/{taskId}/identitylinks/groups

Returns only identity links targeting either users or groups. Response body and status-codes are exactly the same as when getting the full list of identity links for a task.

### Get a single identity link on a task

    GET runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}

<table>
<caption>Get all identitylinks for a task for either groups or users - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task .</p></td>
</tr>
<tr class="even">
<td><p>family</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Either groups or users, depending on what kind of identity is targeted.</p></td>
</tr>
<tr class="odd">
<td><p>identityId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the identity.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The type of identity link.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get all identitylinks for a task for either groups or users - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task and identity link was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have the requested identityLink. The status contains additional information about this error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "userId" : null,
      "groupId" : "sales",
      "type" : "candidate",
      "url" : "http://localhost:8081/flowable-rest/service/runtime/tasks/100/identitylinks/groups/sales/candidate"
    }

### Create an identity link on a task

    POST runtime/tasks/{taskId}/identitylinks

<table>
<caption>Create an identity link on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task .</p></td>
</tr>
</tbody>
</table>

**Request body (user):**

    {
      "userId" : "kermit",
      "type" : "candidate",
    }

**Request body (group):**

    {
      "groupId" : "sales",
      "type" : "candidate",
    }

<table>
<caption>Create an identity link on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the task was found and the identity link was created.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have the requested identityLink. The status contains additional information about this error.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "userId" : null,
      "groupId" : "sales",
      "type" : "candidate",
      "url" : "http://localhost:8081/flowable-rest/service/runtime/tasks/100/identitylinks/groups/sales/candidate"
    }

### Delete an identity link on a task

    DELETE runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}

<table>
<caption>Delete an identity link on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task.</p></td>
</tr>
<tr class="even">
<td><p>family</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>Either groups or users, depending on what kind of identity is targeted.</p></td>
</tr>
<tr class="odd">
<td><p>identityId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the identity.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The type of identity link.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete an identity link on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the task and identity link were found and the link has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have the requested identityLink. The status contains additional information about this error.</p></td>
</tr>
</tbody>
</table>

### Create a new comment on a task

    POST runtime/tasks/{taskId}/comments

<table>
<caption>Create a new comment on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to create the comment for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

    {
      "message" : "This is a comment on the task.",
      "saveProcessInstanceId" : true
    }

Parameter saveProcessInstanceId is optional, if true save process instance id of task with comment.

**Success response body:**

    {
      "id" : "123",
      "taskUrl" : "http://localhost:8081/flowable-rest/service/runtime/tasks/101/comments/123",
      "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/123",
      "message" : "This is a comment on the task.",
      "author" : "kermit",
      "time" : "2014-07-13T13:13:52.232+08:00"
      "taskId" : "101",
      "processInstanceId" : "100"
    }

<table>
<caption>Create a new comment on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the comment was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the comment is missing from the request.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get all comments on a task

    GET runtime/tasks/{taskId}/comments

<table>
<caption>Get all comments on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the comments for.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "id" : "123",
        "taskUrl" : "http://localhost:8081/flowable-rest/service/runtime/tasks/101/comments/123",
        "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/123",
        "message" : "This is a comment on the task.",
        "author" : "kermit"
        "time" : "2014-07-13T13:13:52.232+08:00"
        "taskId" : "101",
        "processInstanceId" : "100"
      },
      {
        "id" : "456",
        "taskUrl" : "http://localhost:8081/flowable-rest/service/runtime/tasks/101/comments/456",
        "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/456",
        "message" : "This is another comment on the task.",
        "author" : "gonzo",
        "time" : "2014-07-13T13:13:52.232+08:00"
        "taskId" : "101",
        "processInstanceId" : "100"
      }
    ]

<table>
<caption>Get all comments on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the comments are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get a comment on a task

    GET runtime/tasks/{taskId}/comments/{commentId}

<table>
<caption>Get a comment on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the comment for.</p></td>
</tr>
<tr class="even">
<td><p>commentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the comment.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id" : "123",
      "taskUrl" : "http://localhost:8081/flowable-rest/service/runtime/tasks/101/comments/123",
      "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/123",
      "message" : "This is a comment on the task.",
      "author" : "kermit",
      "time" : "2014-07-13T13:13:52.232+08:00"
      "taskId" : "101",
      "processInstanceId" : "100"
    }

<table>
<caption>Get a comment on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task and comment were found and the comment is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the tasks doesn’t have a comment with the given ID.</p></td>
</tr>
</tbody>
</table>

### Delete a comment on a task

    DELETE runtime/tasks/{taskId}/comments/{commentId}

<table>
<caption>Delete a comment on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to delete the comment for.</p></td>
</tr>
<tr class="even">
<td><p>commentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the comment.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a comment on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the task and comment were found and the comment is deleted. Response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the tasks doesn’t have a comment with the given ID.</p></td>
</tr>
</tbody>
</table>

### Get all events for a task

    GET runtime/tasks/{taskId}/events

<table>
<caption>Get all events for a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the events for.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "action" : "AddUserLink",
        "id" : "4",
        "message" : [ "gonzo", "contributor" ],
        "taskUrl" : "http://localhost:8182/runtime/tasks/2",
        "time" : "2013-05-17T11:50:50.000+0000",
        "url" : "http://localhost:8182/runtime/tasks/2/events/4",
        "userId" : null
      }

    ]

<table>
<caption>Get all events for a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the events are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get an event on a task

    GET runtime/tasks/{taskId}/events/{eventId}

<table>
<caption>Get an event on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the event for.</p></td>
</tr>
<tr class="even">
<td><p>eventId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the event.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "action" : "AddUserLink",
      "id" : "4",
      "message" : [ "gonzo", "contributor" ],
      "taskUrl" : "http://localhost:8182/runtime/tasks/2",
      "time" : "2013-05-17T11:50:50.000+0000",
      "url" : "http://localhost:8182/runtime/tasks/2/events/4",
      "userId" : null
    }

<table>
<caption>Get an event on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task and event were found and the event is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the tasks doesn’t have an event with the given ID.</p></td>
</tr>
</tbody>
</table>

### Create a new attachment on a task, containing a link to an external resource

    POST runtime/tasks/{taskId}/attachments

<table>
<caption>Create a new attachment on a task, containing a link to an external resource - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to create the attachment for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

    {
      "name":"Simple attachment",
      "description":"Simple attachment description",
      "type":"simpleType",
      "externalUrl":"http://flowable.org"
    }

Only the attachment name is required to create a new attachment.

**Success response body:**

    {
      "id":"3",
      "url":"http://localhost:8182/runtime/tasks/2/attachments/3",
      "name":"Simple attachment",
      "description":"Simple attachment description",
      "type":"simpleType",
      "taskUrl":"http://localhost:8182/runtime/tasks/2",
      "processInstanceUrl":null,
      "externalUrl":"http://flowable.org",
      "contentUrl":null
    }

<table>
<caption>Create a new attachment on a task, containing a link to an external resource - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the attachment was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the attachment name is missing from the request.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Create a new attachment on a task, with an attached file

    POST runtime/tasks/{taskId}/attachments

<table>
<caption>Create a new attachment on a task, with an attached file - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to create the attachment for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

-   name: Required name of the variable.

-   description: Description of the attachment, optional.

-   type: Type of attachment, optional. Supports any arbitrary string or a valid HTTP content-type.

**Success response body:**

    {
        "id":"5",
        "url":"http://localhost:8182/runtime/tasks/2/attachments/5",
        "name":"Binary attachment",
        "description":"Binary attachment description",
        "type":"binaryType",
        "taskUrl":"http://localhost:8182/runtime/tasks/2",
        "processInstanceUrl":null,
        "externalUrl":null,
        "contentUrl":"http://localhost:8182/runtime/tasks/2/attachments/5/content"
    }

<table>
<caption>Create a new attachment on a task, with an attached file - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the attachment was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the attachment name is missing from the request or no file was present in the request. The error-message contains additional information.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get all attachments on a task

    GET runtime/tasks/{taskId}/attachments

<table>
<caption>Get all attachments on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the attachments for.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "id":"3",
        "url":"http://localhost:8182/runtime/tasks/2/attachments/3",
        "name":"Simple attachment",
        "description":"Simple attachment description",
        "type":"simpleType",
        "taskUrl":"http://localhost:8182/runtime/tasks/2",
        "processInstanceUrl":null,
        "externalUrl":"http://flowable.org",
        "contentUrl":null
      },
      {
        "id":"5",
        "url":"http://localhost:8182/runtime/tasks/2/attachments/5",
        "name":"Binary attachment",
        "description":"Binary attachment description",
        "type":"binaryType",
        "taskUrl":"http://localhost:8182/runtime/tasks/2",
        "processInstanceUrl":null,
        "externalUrl":null,
        "contentUrl":"http://localhost:8182/runtime/tasks/2/attachments/5/content"
      }
    ]

<table>
<caption>Get all attachments on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task was found and the attachments are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get an attachment on a task

    GET runtime/tasks/{taskId}/attachments/{attachmentId}

<table>
<caption>Get an attachment on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get the attachment for.</p></td>
</tr>
<tr class="even">
<td><p>attachmentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the attachment.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id":"5",
      "url":"http://localhost:8182/runtime/tasks/2/attachments/5",
      "name":"Binary attachment",
      "description":"Binary attachment description",
      "type":"binaryType",
      "taskUrl":"http://localhost:8182/runtime/tasks/2",
      "processInstanceUrl":null,
      "externalUrl":null,
      "contentUrl":"http://localhost:8182/runtime/tasks/2/attachments/5/content"
    }

-   externalUrl - contentUrl:In case the attachment is a link to an external resource, the externalUrl contains the URL to the external content. If the attachment content is present in the Flowable engine, the contentUrl will contain an URL where the binary content can be streamed from.

-   type:Can be any arbitrary value. When a valid formatted media-type (e.g. application/xml, text/plain) is included, the binary content HTTP response content-type will be set the given value.

<table>
<caption>Get an attachment on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task and attachment were found and the attachment is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the tasks doesn’t have a attachment with the given ID.</p></td>
</tr>
</tbody>
</table>

### Get the content for an attachment

    GET runtime/tasks/{taskId}/attachment/{attachmentId}/content

<table>
<caption>Get the content for an attachment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to get a variable data for.</p></td>
</tr>
<tr class="even">
<td><p>attachmentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the attachment, a 404 is returned when the attachment points to an external URL rather than content attached in Flowable.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get the content for an attachment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task and attachment was found and the requested content is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the task doesn’t have an attachment with the given id or the attachment doesn’t have a binary stream available. Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body contains the binary content. By default, the content-type of the response is set to application/octet-stream unless the attachment type contains a valid Content-type.

### Delete an attachment on a task

    DELETE runtime/tasks/{taskId}/attachments/{attachmentId}

<table>
<caption>Delete an attachment on a task - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the task to delete the attachment for.</p></td>
</tr>
<tr class="even">
<td><p>attachmentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the attachment.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete an attachment on a task - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the task and attachment were found and the attachment is deleted. Response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the tasks doesn’t have a attachment with the given ID.</p></td>
</tr>
</tbody>
</table>

## History

### Get a historic process instance

    GET history/historic-process-instances/{processInstanceId}

<table>
<caption>Get a historic process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that the historic process instances could be found.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates that the historic process instances could not be found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id" : "5",
      "businessKey" : "myKey",
      "processDefinitionId" : "oneTaskProcess%3A1%3A4",
      "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
      "startTime" : "2013-04-17T10:17:43.902+0000",
      "endTime" : "2013-04-18T14:06:32.715+0000",
      "durationInMillis" : 86400056,
      "startUserId" : "kermit",
      "startActivityId" : "startEvent",
      "endActivityId" : "endEvent",
      "deleteReason" : null,
      "superProcessInstanceId" : "3",
      "url" : "http://localhost:8182/history/historic-process-instances/5",
      "variables": null,
      "tenantId":null
    }

### List of historic process instances

    GET history/historic-process-instances

<table>
<caption>List of historic process instances - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An id of the historic process instance.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition key of the historic process instance.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition id of the historic process instance.</p></td>
</tr>
<tr class="even">
<td><p>businessKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The business key of the historic process instance.</p></td>
</tr>
<tr class="odd">
<td><p>involvedUser</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An involved user of the historic process instance.</p></td>
</tr>
<tr class="even">
<td><p>finished</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication if the historic process instance is finished.</p></td>
</tr>
<tr class="odd">
<td><p>superProcessInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An optional parent process id of the historic process instance.</p></td>
</tr>
<tr class="even">
<td><p>excludeSubprocesses</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Return only historic process instances which aren’t sub processes.</p></td>
</tr>
<tr class="odd">
<td><p>finishedAfter</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic process instances that were finished after this date.</p></td>
</tr>
<tr class="even">
<td><p>finishedBefore</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic process instances that were finished before this date.</p></td>
</tr>
<tr class="odd">
<td><p>startedAfter</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic process instances that were started after this date.</p></td>
</tr>
<tr class="even">
<td><p>startedBefore</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic process instances that were started before this date.</p></td>
</tr>
<tr class="odd">
<td><p>startedBy</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Return only historic process instances that were started by this user.</p></td>
</tr>
<tr class="even">
<td><p>includeProcessVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>An indication if the historic process instance variables should be returned as well.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return instances with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return instances with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns instances without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of historic process instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that historic process instances could be queried.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "5",
          "businessKey" : "myKey",
          "processDefinitionId" : "oneTaskProcess%3A1%3A4",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "startTime" : "2013-04-17T10:17:43.902+0000",
          "endTime" : "2013-04-18T14:06:32.715+0000",
          "durationInMillis" : 86400056,
          "startUserId" : "kermit",
          "startActivityId" : "startEvent",
          "endActivityId" : "endEvent",
          "deleteReason" : null,
          "superProcessInstanceId" : "3",
          "url" : "http://localhost:8182/history/historic-process-instances/5",
          "variables": [
            {
              "name": "test",
              "variableScope": "local",
              "value": "myTest"
            }
          ],
          "tenantId":null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Query for historic process instances

    POST query/historic-process-instances

**Request body:**

    {
      "processDefinitionId" : "oneTaskProcess%3A1%3A4",


      "variables" : [
        {
          "name" : "myVariable",
          "value" : 1234,
          "operation" : "equals",
          "type" : "long"
        }
      ]
    }

All supported JSON parameter fields allowed are exactly the same as the parameters found for [getting a collection of historic process instances](bpmn/ch14-REST.md#list-of-historic-process-instances), but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri’s that are too long. On top of that, the query allows for filtering based on process variables. The variables property is a JSON-array containing objects with the format [as described here.](#json-query-variable-format)

<table>
<caption>Query for historic process instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the tasks are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "5",
          "businessKey" : "myKey",
          "processDefinitionId" : "oneTaskProcess%3A1%3A4",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "startTime" : "2013-04-17T10:17:43.902+0000",
          "endTime" : "2013-04-18T14:06:32.715+0000",
          "durationInMillis" : 86400056,
          "startUserId" : "kermit",
          "startActivityId" : "startEvent",
          "endActivityId" : "endEvent",
          "deleteReason" : null,
          "superProcessInstanceId" : "3",
          "url" : "http://localhost:8182/history/historic-process-instances/5",
          "variables": [
            {
              "name": "test",
              "variableScope": "local",
              "value": "myTest"
            }
          ],
          "tenantId":null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Delete a historic process instance

    DELETE history/historic-process-instances/{processInstanceId}

<table>
<caption>Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that the historic process instance was deleted.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates that the historic process instance could not be found.</p></td>
</tr>
</tbody>
</table>

### Get the identity links of a historic process instance

    GET history/historic-process-instance/{processInstanceId}/identitylinks

<table>
<caption>Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the identity links are returned</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the process instance could not be found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
     {
      "type" : "participant",
      "userId" : "kermit",
      "groupId" : null,
      "taskId" : null,
      "taskUrl" : null,
      "processInstanceId" : "5",
      "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/5"
     }
    ]

### Get the binary data for a historic process instance variable

    GET history/historic-process-instances/{processInstanceId}/variables/{variableName}/data

<table>
<caption>Get the binary data for a historic process instance variable - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and the requested variable data is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested process instance was not found or the process instance doesn’t have a variable with the given name or the variable doesn’t have a binary stream available. Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body contains the binary value of the variable. When the variable is of type binary, the content-type of the response is set to application/octet-stream, regardless of the content of the variable or the request accept-type header. In case of serializable, application/x-java-serialized-object is used as content-type.

### Create a new comment on a historic process instance

    POST history/historic-process-instances/{processInstanceId}/comments

<table>
<caption>Create a new comment on a historic process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to create the comment for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

    {
      "message" : "This is a comment.",
      "saveProcessInstanceId" : true
    }

Parameter saveProcessInstanceId is optional, if true save process instance id of task with comment.

**Success response body:**

    {
      "id" : "123",
      "taskUrl" : "http://localhost:8081/flowable-rest/service/runtime/tasks/101/comments/123",
      "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/123",
      "message" : "This is a comment on the task.",
      "author" : "kermit",
      "time" : "2014-07-13T13:13:52.232+08:00",
      "taskId" : "101",
      "processInstanceId" : "100"
    }

<table>
<caption>Create a new comment on a historic process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the comment was created and the result is returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the comment is missing from the request.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested historic process instance was not found.</p></td>
</tr>
</tbody>
</table>

### Get all comments on a historic process instance

    GET history/historic-process-instances/{processInstanceId}/comments

<table>
<caption>Get all comments on a process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the process instance to get the comments for.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
      {
        "id" : "123",
        "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/123",
        "message" : "This is a comment on the task.",
        "author" : "kermit",
        "time" : "2014-07-13T13:13:52.232+08:00",
        "processInstanceId" : "100"
      },
      {
        "id" : "456",
        "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/456",
        "message" : "This is another comment.",
        "author" : "gonzo",
        "time" : "2014-07-14T15:16:52.232+08:00",
        "processInstanceId" : "100"
      }
    ]

<table>
<caption>Get all comments on a process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the process instance was found and the comments are returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found.</p></td>
</tr>
</tbody>
</table>

### Get a comment on a historic process instance

    GET history/historic-process-instances/{processInstanceId}/comments/{commentId}

<table>
<caption>Get a comment on a historic process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the historic process instance to get the comment for.</p></td>
</tr>
<tr class="even">
<td><p>commentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the comment.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id" : "123",
      "processInstanceUrl" : "http://localhost:8081/flowable-rest/service/history/historic-process-instances/100/comments/456",
      "message" : "This is another comment.",
      "author" : "gonzo",
      "time" : "2014-07-14T15:16:52.232+08:00",
      "processInstanceId" : "100"
    }

<table>
<caption>Get a comment on a historic process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the historic process instance and comment were found and the comment is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested historic process instance was not found or the historic process instance doesn’t have a comment with the given ID.</p></td>
</tr>
</tbody>
</table>

### Delete a comment on a historic process instance

    DELETE history/historic-process-instances/{processInstanceId}/comments/{commentId}

<table>
<caption>Delete a comment on a historic process instance - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the historic process instance to delete the comment for.</p></td>
</tr>
<tr class="even">
<td><p>commentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the comment.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a comment on a historic process instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the historic process instance and comment were found and the comment is deleted. Response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task was not found or the historic process instance doesn’t have a comment with the given ID.</p></td>
</tr>
</tbody>
</table>

### Get a single historic task instance

    GET history/historic-task-instances/{taskId}

<table>
<caption>Get a single historic task instance - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that the historic task instances could be found.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates that the historic task instances could not be found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id" : "5",
      "processDefinitionId" : "oneTaskProcess%3A1%3A4",
      "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
      "processInstanceId" : "3",
      "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/3",
      "executionId" : "4",
      "name" : "My task name",
      "description" : "My task description",
      "deleteReason" : null,
      "owner" : "kermit",
      "assignee" : "fozzie",
      "startTime" : "2013-04-17T10:17:43.902+0000",
      "endTime" : "2013-04-18T14:06:32.715+0000",
      "durationInMillis" : 86400056,
      "workTimeInMillis" : 234890,
      "claimTime" : "2013-04-18T11:01:54.715+0000",
      "taskDefinitionKey" : "taskKey",
      "formKey" : null,
      "priority" : 50,
      "dueDate" : "2013-04-20T12:11:13.134+0000",
      "parentTaskId" : null,
      "url" : "http://localhost:8182/history/historic-task-instances/5",
      "variables": null,
      "tenantId":null
    }

### Get historic task instances

    GET history/historic-task-instances

<table>
<caption>Get historic task instances - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An id of the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process instance id of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition key of the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionKeyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition key of the historic task instance, which matches the given value.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition id of the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition name of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition name of the historic task instance, which matches the given value.</p></td>
</tr>
<tr class="even">
<td><p>processBusinessKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process instance business key of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>processBusinessKeyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process instance business key of the historic task instance that matches the given value.</p></td>
</tr>
<tr class="even">
<td><p>executionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The execution id of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task definition key for tasks part of a process</p></td>
</tr>
<tr class="even">
<td><p>taskName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task name of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task name with 'like' operator for the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>taskDescription</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task description of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskDescriptionLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task description with 'like' operator for the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>taskDefinitionKey</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task identifier from the process definition for the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskCategory</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Select tasks with the given category. Note that this is the task category, not the category of the process definition (namespace within the BPMN Xml).</p></td>
</tr>
<tr class="even">
<td><p>taskDeleteReason</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task delete reason of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskDeleteReasonLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task delete reason with 'like' operator for the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>taskAssignee</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The assignee of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskAssigneeLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The assignee with 'like' operator for the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>taskOwner</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The owner of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskOwnerLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The owner with 'like' operator for the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>taskInvolvedUser</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An involved user of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>taskPriority</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The priority of the historic task instance.</p></td>
</tr>
<tr class="even">
<td><p>finished</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication if the historic task instance is finished.</p></td>
</tr>
<tr class="odd">
<td><p>processFinished</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication if the process instance of the historic task instance is finished.</p></td>
</tr>
<tr class="even">
<td><p>parentTaskId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An optional parent task id of the historic task instance.</p></td>
</tr>
<tr class="odd">
<td><p>dueDate</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that have a due date equal this date.</p></td>
</tr>
<tr class="even">
<td><p>dueDateAfter</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that have a due date after this date.</p></td>
</tr>
<tr class="odd">
<td><p>dueDateBefore</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that have a due date before this date.</p></td>
</tr>
<tr class="even">
<td><p>withoutDueDate</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Return only historic task instances that have no due-date. When false is provided as value, this parameter is ignored.</p></td>
</tr>
<tr class="odd">
<td><p>taskCompletedOn</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that have been completed on this date.</p></td>
</tr>
<tr class="even">
<td><p>taskCompletedAfter</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that have been completed after this date.</p></td>
</tr>
<tr class="odd">
<td><p>taskCompletedBefore</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that have been completed before this date.</p></td>
</tr>
<tr class="even">
<td><p>taskCreatedOn</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that were created on this date.</p></td>
</tr>
<tr class="odd">
<td><p>taskCreatedBefore</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that were created before this date.</p></td>
</tr>
<tr class="even">
<td><p>taskCreatedAfter</p></td>
<td><p>No</p></td>
<td><p>Date</p></td>
<td><p>Return only historic task instances that were created after this date.</p></td>
</tr>
<tr class="odd">
<td><p>includeTaskLocalVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>An indication if the historic task instance local variables should be returned as well.</p></td>
</tr>
<tr class="even">
<td><p>includeProcessVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>An indication if the historic task instance global variables should be returned as well.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return historic task instances with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return historic task instances with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns historic task instances without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get historic task instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that historic process instances could be queried.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "5",
          "processDefinitionId" : "oneTaskProcess%3A1%3A4",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "processInstanceId" : "3",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/3",
          "executionId" : "4",
          "name" : "My task name",
          "description" : "My task description",
          "deleteReason" : null,
          "owner" : "kermit",
          "assignee" : "fozzie",
          "startTime" : "2013-04-17T10:17:43.902+0000",
          "endTime" : "2013-04-18T14:06:32.715+0000",
          "durationInMillis" : 86400056,
          "workTimeInMillis" : 234890,
          "claimTime" : "2013-04-18T11:01:54.715+0000",
          "taskDefinitionKey" : "taskKey",
          "formKey" : null,
          "priority" : 50,
          "dueDate" : "2013-04-20T12:11:13.134+0000",
          "parentTaskId" : null,
          "url" : "http://localhost:8182/history/historic-task-instances/5",
          "taskVariables": [
            {
              "name": "test",
              "variableScope": "local",
              "value": "myTest"
            }
          ],
          "processVariables": [
            {
              "name": "processTest",
              "variableScope": "global",
              "value": "myProcessTest"
            }
          ],
          "tenantId":null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Query for historic task instances

    POST query/historic-task-instances

**Query for historic task instances - Request body:**

    {
      "processDefinitionId" : "oneTaskProcess%3A1%3A4",
      ...

      "variables" : [
        {
          "name" : "myVariable",
          "value" : 1234,
          "operation" : "equals",
          "type" : "long"
        }
      ]
    }

All supported JSON parameter fields allowed are exactly the same as the parameters found for [getting a collection of historic task instances](bpmn/ch14-REST.md#get-historic-task-instances), but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri’s that are too long. On top of that, the query allows for filtering based on process variables. The taskVariables and processVariables properties are JSON-arrays containing objects with the format [as described here.](#json-query-variable-format)

<table>
<caption>Query for historic task instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the tasks are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "5",
          "processDefinitionId" : "oneTaskProcess%3A1%3A4",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "processInstanceId" : "3",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/3",
          "executionId" : "4",
          "name" : "My task name",
          "description" : "My task description",
          "deleteReason" : null,
          "owner" : "kermit",
          "assignee" : "fozzie",
          "startTime" : "2013-04-17T10:17:43.902+0000",
          "endTime" : "2013-04-18T14:06:32.715+0000",
          "durationInMillis" : 86400056,
          "workTimeInMillis" : 234890,
          "claimTime" : "2013-04-18T11:01:54.715+0000",
          "taskDefinitionKey" : "taskKey",
          "formKey" : null,
          "priority" : 50,
          "dueDate" : "2013-04-20T12:11:13.134+0000",
          "parentTaskId" : null,
          "url" : "http://localhost:8182/history/historic-task-instances/5",
          "taskVariables": [
            {
              "name": "test",
              "variableScope": "local",
              "value": "myTest"
            }
          ],
          "processVariables": [
            {
              "name": "processTest",
              "variableScope": "global",
              "value": "myProcessTest"
            }
          ],
          "tenantId":null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Delete a historic task instance

    DELETE history/historic-task-instances/{taskId}

<table>
<caption>Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that the historic task instance was deleted.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates that the historic task instance could not be found.</p></td>
</tr>
</tbody>
</table>

### Get the identity links of a historic task instance

    GET history/historic-task-instance/{taskId}/identitylinks

<table>
<caption>Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the identity links are returned</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the task instance could not be found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
     {
      "type" : "assignee",
      "userId" : "kermit",
      "groupId" : null,
      "taskId" : "6",
      "taskUrl" : "http://localhost:8182/history/historic-task-instances/5",
      "processInstanceId" : null,
      "processInstanceUrl" : null
     }
    ]

### Get the binary data for a historic task instance variable

    GET history/historic-task-instances/{taskId}/variables/{variableName}/data

<table>
<caption>Get the binary data for a historic task instance variable - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the task instance was found and the requested variable data is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested task instance was not found or the process instance doesn’t have a variable with the given name or the variable doesn’t have a binary stream available. Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body contains the binary value of the variable. When the variable is of type binary, the content-type of the response is set to application/octet-stream, regardless of the content of the variable or the request accept-type header. In case of serializable, application/x-java-serialized-object is used as content-type.

### Get historic activity instances

    GET history/historic-activity-instances

<table>
<caption>Get historic activity instances - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>activityId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An id of the activity instance.</p></td>
</tr>
<tr class="even">
<td><p>activityInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>An id of the historic activity instance.</p></td>
</tr>
<tr class="odd">
<td><p>activityName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The name of the historic activity instance.</p></td>
</tr>
<tr class="even">
<td><p>activityType</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The element type of the historic activity instance.</p></td>
</tr>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The execution id of the historic activity instance.</p></td>
</tr>
<tr class="even">
<td><p>finished</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication if the historic activity instance is finished.</p></td>
</tr>
<tr class="odd">
<td><p>taskAssignee</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The assignee of the historic activity instance.</p></td>
</tr>
<tr class="even">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process instance id of the historic activity instance.</p></td>
</tr>
<tr class="odd">
<td><p>processDefinitionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process definition id of the historic activity instance.</p></td>
</tr>
<tr class="even">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return instances with the given tenantId.</p></td>
</tr>
<tr class="odd">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return instances with a tenantId like the given value.</p></td>
</tr>
<tr class="even">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns instances without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get historic activity instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that historic activity instances could be queried.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "5",
          "activityId" : "4",
          "activityName" : "My user task",
          "activityType" : "userTask",
          "processDefinitionId" : "oneTaskProcess%3A1%3A4",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "processInstanceId" : "3",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/3",
          "executionId" : "4",
          "taskId" : "4",
          "calledProcessInstanceId" : null,
          "assignee" : "fozzie",
          "startTime" : "2013-04-17T10:17:43.902+0000",
          "endTime" : "2013-04-18T14:06:32.715+0000",
          "durationInMillis" : 86400056,
          "tenantId":null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Query for historic activity instances

    POST query/historic-activity-instances

**Request body:**

    {
      "processDefinitionId" : "oneTaskProcess%3A1%3A4"
    }

All supported JSON parameter fields allowed are exactly the same as the parameters found for [getting a collection of historic task instances](bpmn/ch14-REST.md#get-historic-task-instances), but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri’s that are too long.

<table>
<caption>Query for historic activity instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the activities are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "5",
          "activityId" : "4",
          "activityName" : "My user task",
          "activityType" : "userTask",
          "processDefinitionId" : "oneTaskProcess%3A1%3A4",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
          "processInstanceId" : "3",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/3",
          "executionId" : "4",
          "taskId" : "4",
          "calledProcessInstanceId" : null,
          "assignee" : "fozzie",
          "startTime" : "2013-04-17T10:17:43.902+0000",
          "endTime" : "2013-04-18T14:06:32.715+0000",
          "durationInMillis" : 86400056,
          "tenantId":null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### List of historic variable instances

    GET history/historic-variable-instances

<table>
<caption>List of historic variable instances - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process instance id of the historic variable instance.</p></td>
</tr>
<tr class="even">
<td><p>taskId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task id of the historic variable instance.</p></td>
</tr>
<tr class="odd">
<td><p>excludeTaskVariables</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication to exclude the task variables from the result.</p></td>
</tr>
<tr class="even">
<td><p>variableName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The variable name of the historic variable instance.</p></td>
</tr>
<tr class="odd">
<td><p>variableNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The variable name using the 'like' operator for the historic variable instance.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of historic variable instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that historic variable instances could be queried.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "14",
          "processInstanceId" : "5",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/5",
          "taskId" : "6",
          "variable" : {
            "name" : "myVariable",
            "variableScope": "global",
            "value" : "test"
          }
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Query for historic variable instances

    POST query/historic-variable-instances

**Request body:**

    {
      "processDefinitionId" : "oneTaskProcess%3A1%3A4",
      ...

      "variables" : [
        {
          "name" : "myVariable",
          "value" : 1234,
          "operation" : "equals",
          "type" : "long"
        }
      ]
    }

All supported JSON parameter fields allowed are exactly the same as the parameters found for [getting a collection of historic process instances](bpmn/ch14-REST.md#list-of-historic-variable-instances), but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri’s that are too long. On top of that, the query allows for filtering based on process variables. The variables property is a JSON-array containing objects with the format [as described here.](#json-query-variable-format)

<table>
<caption>Query for historic variable instances - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the tasks are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "14",
          "processInstanceId" : "5",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/5",
          "taskId" : "6",
          "variable" : {
            "name" : "myVariable",
            "variableScope": "global",
            "value" : "test"
          }
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

====Get the binary data for a historic task instance variable

    GET history/historic-variable-instances/{varInstanceId}/data

<table>
<caption>Get the binary data for a historic task instance variable - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the variable instance was found and the requested variable data is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested variable instance was not found or the variable instance doesn’t have a variable with the given name or the variable doesn’t have a binary stream available. Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body contains the binary value of the variable. When the variable is of type binary, the content-type of the response is set to application/octet-stream, regardless of the content of the variable or the request accept-type header. In case of serializable, application/x-java-serialized-object is used as content-type.

### Get historic detail

    GET history/historic-detail

<table>
<caption>Get historic detail - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The id of the historic detail.</p></td>
</tr>
<tr class="even">
<td><p>processInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The process instance id of the historic detail.</p></td>
</tr>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The execution id of the historic detail.</p></td>
</tr>
<tr class="even">
<td><p>activityInstanceId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The activity instance id of the historic detail.</p></td>
</tr>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>The task id of the historic detail.</p></td>
</tr>
<tr class="even">
<td><p>selectOnlyFormProperties</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication to only return form properties in the result.</p></td>
</tr>
<tr class="odd">
<td><p>selectOnlyVariableUpdates</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Indication to only return variable updates in the result.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get historic detail - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that historic detail could be queried.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "26",
          "processInstanceId" : "5",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/5",
          "executionId" : "6",
          "activityInstanceId", "10",
          "taskId" : "6",
          "taskUrl" : "http://localhost:8182/history/historic-task-instances/6",
          "time" : "2013-04-17T10:17:43.902+0000",
          "detailType" : "variableUpdate",
          "revision" : 2,
          "variable" : {
            "name" : "myVariable",
            "variableScope": "global",
            "value" : "test"
          },
          "propertyId": null,
          "propertyValue": null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Query for historic details

    POST query/historic-detail

**Request body:**

    {
      "processInstanceId" : "5",
    }

All supported JSON parameter fields allowed are exactly the same as the parameters found for [getting a collection of historic process instances](bpmn/ch14-REST.md#get-historic-detail), but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri’s that are too long.

<table>
<caption>Query for historic details - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the historic details are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id" : "26",
          "processInstanceId" : "5",
          "processInstanceUrl" : "http://localhost:8182/history/historic-process-instances/5",
          "executionId" : "6",
          "activityInstanceId", "10",
          "taskId" : "6",
          "taskUrl" : "http://localhost:8182/history/historic-task-instances/6",
          "time" : "2013-04-17T10:17:43.902+0000",
          "detailType" : "variableUpdate",
          "revision" : 2,
          "variable" : {
            "name" : "myVariable",
            "variableScope": "global",
            "value" : "test"
          },
          "propertyId" : null,
          "propertyValue" : null
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Get the binary data for a historic detail variable

    GET history/historic-detail/{detailId}/data

<table>
<caption>Get the binary data for a historic detail variable - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the historic detail instance was found and the requested variable data is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested historic detail instance was not found or the historic detail instance doesn’t have a variable with the given name or the variable doesn’t have a binary stream available. Status message provides additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body contains the binary value of the variable. When the variable is of type binary, the content-type of the response is set to application/octet-stream, regardless of the content of the variable or the request accept-type header. In case of serializable, application/x-java-serialized-object is used as content-type.

## Forms

### Get form data

    GET form/form-data

<table>
<caption>Get form data - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>taskId</p></td>
<td><p>Yes (if no processDefinitionId)</p></td>
<td><p>String</p></td>
<td><p>The task id corresponding to the form data that needs to be retrieved.</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionId</p></td>
<td><p>Yes (if no taskId)</p></td>
<td><p>String</p></td>
<td><p>The process definition id corresponding to the start event form data that needs to be retrieved.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get form data - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates that form data could be queried.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates that form data could not be found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "formKey" : null,
          "deploymentId" : "2",
          "processDefinitionId" : "3",
          "processDefinitionUrl" : "http://localhost:8182/repository/process-definition/3",
          "taskId" : "6",
          "taskUrl" : "http://localhost:8182/runtime/task/6",
          "formProperties" : [
            {
              "id" : "room",
              "name" : "Room",
              "type" : "string",
              "value" : null,
              "readable" : true,
              "writable" : true,
              "required" : true,
              "datePattern" : null,
              "enumValues" : [
                {
                  "id" : "normal",
                  "name" : "Normal bed"
                },
                {
                  "id" : "kingsize",
                  "name" : "Kingsize bed"
                },
              ]
            }
          ]
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Submit task form data

    POST form/form-data

**Request body for task form:**

    {
      "taskId" : "5",
      "properties" : [
        {
          "id" : "room",
          "value" : "normal"
        }
      ]
    }

**Request body for start event form:**

    {
      "processDefinitionId" : "5",
      "businessKey" : "myKey",
      "properties" : [
        {
          "id" : "room",
          "value" : "normal"
        }
      ]
    }

<table>
<caption>Submit task form data - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the form data was submitted</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an parameter was passed in the wrong format. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body for start event form data (no response for task form data):**

    {
      "id" : "5",
      "url" : "http://localhost:8182/history/historic-process-instances/5",
      "businessKey" : "myKey",
      "suspended": false,
      "processDefinitionId" : "3",
      "processDefinitionUrl" : "http://localhost:8182/repository/process-definition/3",
      "activityId" : "myTask"
    }

## Database tables

### List of tables

    GET management/tables

<table>
<caption>List of tables - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the request was successful.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    [
       {
          "name":"ACT_RU_VARIABLE",
          "url":"http://localhost:8182/management/tables/ACT_RU_VARIABLE",
          "count":4528
       },
       {
          "name":"ACT_RU_EVENT_SUBSCR",
          "url":"http://localhost:8182/management/tables/ACT_RU_EVENT_SUBSCR",
          "count":3
       }

    ]

### Get a single table

    GET management/tables/{tableName}

<table>
<caption>Get a single table - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>tableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the table to get.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
          "name":"ACT_RE_PROCDEF",
          "url":"http://localhost:8182/management/tables/ACT_RE_PROCDEF",
          "count":60
    }

<table>
<caption>Get a single table - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the table exists and the table count is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested table does not exist.</p></td>
</tr>
</tbody>
</table>

### Get column info for a single table

    GET management/tables/{tableName}/columns

<table>
<caption>Get column info for a single table - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>tableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the table to get.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "tableName":"ACT_RU_VARIABLE",
       "columnNames":[
          "ID_",
          "REV_",
          "TYPE_",
          "NAME_"


       ],
       "columnTypes":[
          "VARCHAR",
          "INTEGER",
          "VARCHAR",
          "VARCHAR"


       ]
    }

<table>
<caption>Get column info for a single table - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the table exists and the table column info is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested table does not exist.</p></td>
</tr>
</tbody>
</table>

### Get row data for a single table

    GET management/tables/{tableName}/data

<table>
<caption>Get row data for a single table - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>tableName</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The name of the table to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get row data for a single table - URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>start</p></td>
<td><p>No</p></td>
<td><p>Integer</p></td>
<td><p>Index of the first row to fetch. Defaults to 0.</p></td>
</tr>
<tr class="even">
<td><p>size</p></td>
<td><p>No</p></td>
<td><p>Integer</p></td>
<td><p>Number of rows to fetch, starting from start. Defaults to 10.</p></td>
</tr>
<tr class="odd">
<td><p>orderAscendingColumn</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Name of the column to sort the resulting rows on, ascending.</p></td>
</tr>
<tr class="even">
<td><p>orderDescendingColumn</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Name of the column to sort the resulting rows on, descending.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "total":3,
       "start":0,
       "sort":null,
       "order":null,
       "size":3,

       "data":[
          {
             "TASK_ID_":"2",
             "NAME_":"var1",
             "REV_":1,
             "TEXT_":"123",
             "LONG_":123,
             "ID_":"3",
             "TYPE_":"integer"
          }



       ]

    }

<table>
<caption>Get row data for a single table - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the table exists and the table row data is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested table does not exist.</p></td>
</tr>
</tbody>
</table>

## Engine

### Get engine properties

    GET management/properties

Returns a read-only view of the properties used internally in the engine.

**Success response body:**

    {
       "next.dbid":"101",
       "schema.history":"create(5.15)",
       "schema.version":"5.15"
    }

<table>
<caption>Get engine properties - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the properties are returned.</p></td>
</tr>
</tbody>
</table>

### Get engine info

    GET management/engine

Returns a read-only view of the engine that is used in this REST-service.

**Success response body:**

    {
       "name":"default",
       "version":"5.15",
       "resourceUrl":"file://flowable/flowable.cfg.xml",
       "exception":null
    }

<table>
<caption>Get engine info - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the engine info is returned.</p></td>
</tr>
</tbody>
</table>

## Runtime

### Signal event received

    POST runtime/signals

Notifies the engine that a signal event has been received, not explicitly related to a specific execution.

**Body JSON:**

    {
      "signalName": "My Signal",
      "tenantId" : "execute",
      "async": true,
      "variables": [
          {"name": "testVar", "value": "This is a string"}

      ]
    }

<table>
<caption>Signal event received - JSON Body parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>signalName</p></td>
<td><p>Name of the signal</p></td>
<td><p>Yes</p></td>
</tr>
<tr class="even">
<td><p>tenantId</p></td>
<td><p>ID of the tenant that the signal event should be processed in</p></td>
<td><p>No</p></td>
</tr>
<tr class="odd">
<td><p>async</p></td>
<td><p>If true, handling of the signal will happen asynchronously. Return code will be 202 - Accepted to indicate the request is accepted but not yet executed. If false,
handling the signal will be done immediately and result (200 - OK) will only return after this completed successfully. Defaults to false if omitted.</p></td>
<td><p>No</p></td>
</tr>
<tr class="even">
<td><p>variables</p></td>
<td><p>Array of variables (in the general variables format) to use as payload to pass along with the signal. Cannot be used in case async is set to true, this will result in an error.</p></td>
<td><p>No</p></td>
</tr>
</tbody>
</table>

**Success response body:**

<table>
<caption>Signal event received - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicated signal has been processed and no errors occurred.</p></td>
</tr>
<tr class="even">
<td><p>202</p></td>
<td><p>Indicated signal processing is queued as a job, ready to be executed.</p></td>
</tr>
<tr class="odd">
<td><p>400</p></td>
<td><p>Signal not processed. The signal name is missing or variables are used together with async, which is not allowed. Response body contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

## Jobs

### Get a single job

    GET management/jobs/{jobId}

<table>
<caption>Get a single job - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>jobId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the job to get.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"8",
       "url":"http://localhost:8182/management/jobs/8",
       "processInstanceId":"5",
       "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
       "processDefinitionId":"timerProcess:1:4",
       "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/timerProcess%3A1%3A4",
       "executionId":"7",
       "executionUrl":"http://localhost:8182/runtime/executions/7",
       "retries":3,
       "exceptionMessage":null,
       "dueDate":"2013-06-04T22:05:05.474+0000",
       "tenantId":null
    }

<table>
<caption>Get a single job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the job exists and is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested job does not exist.</p></td>
</tr>
</tbody>
</table>

### Delete a job

    DELETE management/jobs/{jobId}

<table>
<caption>Delete a job - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>jobId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the job to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the job was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested job was not found.</p></td>
</tr>
</tbody>
</table>

### Execute a single job

    POST management/jobs/{jobId}

**Body JSON:**

    {
      "action" : "execute"
    }

<table>
<caption>Execute a single job - JSON Body parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>action</p></td>
<td><p>Action to perform. Only execute is supported.</p></td>
<td><p>Yes</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Execute a single job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the job was executed. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested job was not found.</p></td>
</tr>
<tr class="odd">
<td><p>500</p></td>
<td><p>Indicates the an exception occurred while executing the job. The status-description contains additional detail about the error. The full error-stacktrace can be fetched later on if needed.</p></td>
</tr>
</tbody>
</table>

### Get the exception stacktrace for a job

    GET management/jobs/{jobId}/exception-stacktrace

<table>
<caption>Get the exception stacktrace for a job - URL parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>jobId</p></td>
<td><p>Id of the job to get the stacktrace for.</p></td>
<td><p>Yes</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get the exception stacktrace for a job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the requested job was not found and the stacktrace has been returned. The response contains the raw stacktrace and always has a Content-type of text/plain.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested job was not found or the job doesn’t have an exception stacktrace. Status-description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Get a list of jobs

    GET management/jobs

<table>
<caption>Get a list of jobs - URL query parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>Only return job with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>processInstanceId</p></td>
<td><p>Only return jobs part of a process with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Only return jobs part of an execution with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionId</p></td>
<td><p>Only return jobs with the given process definition id</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>withRetriesLeft</p></td>
<td><p>If true, only return jobs with retries left. If false, this parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>executable</p></td>
<td><p>If true, only return jobs which are executable. If false, this parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="odd">
<td><p>timersOnly</p></td>
<td><p>If true, only return jobs which are timers. If false, this parameter is ignored. Cannot be used together with 'messagesOnly'.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>messagesOnly</p></td>
<td><p>If true, only return jobs which are messages. If false, this parameter is ignored. Cannot be used together with 'timersOnly'</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="odd">
<td><p>withException</p></td>
<td><p>If true, only return jobs for which an exception occurred while executing it. If false, this parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>dueBefore</p></td>
<td><p>Only return jobs which are due to be executed before the given date. Jobs without duedate are never returned using this parameter.</p></td>
<td><p>Date</p></td>
</tr>
<tr class="odd">
<td><p>dueAfter</p></td>
<td><p>Only return jobs which are due to be executed after the given date. Jobs without duedate are never returned using this parameter.</p></td>
<td><p>Date</p></td>
</tr>
<tr class="even">
<td><p>exceptionMessage</p></td>
<td><p>Only return jobs with the given exception message</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>Only return jobs with the given tenantId.</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>Only return jobs with a tenantId like the given value.</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>If true, only returns jobs without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>withoutScopeType</p></td>
<td><p>If true, only returns jobs without a scope type set. If false, the withoutScopeType parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>Field to sort results on, should be one of id, dueDate, executionId, processInstanceId, retries or tenantId.</p></td>
<td><p>String</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"13",
             "url":"http://localhost:8182/management/jobs/13",
             "processInstanceId":"5",
             "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
             "processDefinitionId":"timerProcess:1:4",
             "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/timerProcess%3A1%3A4",
             "executionId":"12",
             "executionUrl":"http://localhost:8182/runtime/executions/12",
             "retries":0,
             "exceptionMessage":"Can't find scripting engine for 'unexistinglanguage'",
             "dueDate":"2013-06-07T10:00:24.653+0000",
             "tenantId":null
          }



       ],
       "total":2,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":2
    }

<table>
<caption>Get a list of jobs - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the requested jobs were returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an illegal value has been used in a url query parameter or the both 'messagesOnly' and 'timersOnly' are used as parameters. Status description contains additional details about the error.</p></td>
</tr>
</tbody>
</table>

### Get a single deadletter job

    GET management/deadletter-jobs/{jobId}

<table>
<caption>Get a single dead letter job - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>jobId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the dead letter job to get.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"8",
       "url":"http://localhost:8182/management/jobs/8",
       "processInstanceId":"5",
       "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
       "processDefinitionId":"timerProcess:1:4",
       "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/timerProcess%3A1%3A4",
       "executionId":"7",
       "executionUrl":"http://localhost:8182/runtime/executions/7",
       "retries":0,
       "exceptionMessage":"Can't find scripting engine for 'unexistinglanguage'",
       "dueDate":"2013-06-04T22:05:05.474+0000",
       "tenantId":null
    }

<table>
<caption>Get a single dead letter job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the dead letter job exists and is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested dead letter job does not exist.</p></td>
</tr>
</tbody>
</table>

### Delete a dead letter job

    DELETE management/deadletter-jobs/{jobId}

<table>
<caption>Delete a dead letter job - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>jobId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the dead letter job to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a dead letter job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the dead letter job was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested dead letter job was not found.</p></td>
</tr>
</tbody>
</table>

### Resume and execute a dead letter job

    POST management/deadletter-jobs/{jobId}

**Body JSON:**

    {
      "action" : "move"
    }

<table>
<caption>Resume and execute a dead letter job - JSON Body parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>action</p></td>
<td><p>Action to perform. Only execute is supported.</p></td>
<td><p>Yes</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Resume and execute a dead letter job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the dead letter job was executed. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested dead letter job was not found.</p></td>
</tr>
<tr class="odd">
<td><p>500</p></td>
<td><p>Indicates the an exception occurred while executing the dead letter job. The status-description contains additional detail about the error. The full error-stacktrace can be fetched later on if needed.</p></td>
</tr>
</tbody>
</table>

### Get the exception stacktrace for a deadletter job

    GET management/deadletter-jobs/{jobId}/exception-stacktrace

<table>
<caption>Get the exception stacktrace for a dead letter job - URL parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Required</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>jobId</p></td>
<td><p>Id of the dead letter job to get the stacktrace for.</p></td>
<td><p>Yes</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get the exception stacktrace for a dead letter job - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the requested dead letter job was not found and the stacktrace has been returned. The response contains the raw stacktrace and always has a Content-type of text/plain.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested dead letter job was not found or the job doesn’t have an exception stacktrace. Status-description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Get a list of dead letterjobs

    GET management/deadletter-jobs

<table>
<caption>Get a list of dead letter jobs - URL query parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>Only return job with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>processInstanceId</p></td>
<td><p>Only return jobs part of a process with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>executionId</p></td>
<td><p>Only return jobs part of an execution with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>processDefinitionId</p></td>
<td><p>Only return jobs with the given process definition id</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>executable</p></td>
<td><p>If true, only return jobs which are executable. If false, this parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>timersOnly</p></td>
<td><p>If true, only return jobs which are timers. If false, this parameter is ignored. Cannot be used together with 'messagesOnly'.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="odd">
<td><p>messagesOnly</p></td>
<td><p>If true, only return jobs which are messages. If false, this parameter is ignored. Cannot be used together with 'timersOnly'</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>withException</p></td>
<td><p>If true, only return jobs for which an exception occurred while executing it. If false, this parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="odd">
<td><p>dueBefore</p></td>
<td><p>Only return jobs which are due to be executed before the given date. Jobs without duedate are never returned using this parameter.</p></td>
<td><p>Date</p></td>
</tr>
<tr class="even">
<td><p>dueAfter</p></td>
<td><p>Only return jobs which are due to be executed after the given date. Jobs without duedate are never returned using this parameter.</p></td>
<td><p>Date</p></td>
</tr>
<tr class="odd">
<td><p>withException</p></td>
<td><p>If true, for which an exception occurred while executing it. If false, this parameter is ignored.</p></td>
<td><p>Boolean</p></td>
</tr>
<tr class="even">
<td><p>tenantId</p></td>
<td><p>String</p></td>
<td><p>Only return jobs with exception.</p></td>
</tr>
<tr class="odd">
<td><p>tenantIdLike</p></td>
<td><p>String</p></td>
<td><p>Only return jobs with a tenantId like the given value.</p></td>
</tr>
<tr class="even">
<td><p>withoutTenantId</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns jobs without a tenantId set. If false, this parameter is ignored.</p></td>
</tr>
<tr class="odd">
<td><p>locked</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns jobs which are locked. If false, this parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>unlocked</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns jobs which are unlocked. If false, this parameter is ignored.</p></td>
</tr>
<tr class="odd">
<td><p>withoutScopeType</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns jobs without a scope type set. If false, the withoutScopeType parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>Field to sort results on, should be one of id, dueDate, executionId, processInstanceId, retries or tenantId.</p></td>
<td><p>String</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"13",
             "url":"http://localhost:8182/management/jobs/13",
             "processInstanceId":"5",
             "processInstanceUrl":"http://localhost:8182/runtime/process-instances/5",
             "processDefinitionId":"timerProcess:1:4",
             "processDefinitionUrl":"http://localhost:8182/repository/process-definitions/timerProcess%3A1%3A4",
             "executionId":"12",
             "executionUrl":"http://localhost:8182/runtime/executions/12",
             "retries":0,
             "withException":"Can't find scripting engine for 'unexistinglanguage'",
             "dueDate":"2013-06-07T10:00:24.653+0000",
             "createTime":"2013-06-06T08:08:24.007+0000"
             "tenantId":null
          }
       ],
       "total":2,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":2
    }

<table>
<caption>Get a list of dead letter jobs - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the requested jobs were returned.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates an illegal value has been used in a url query parameter or the both 'messagesOnly' and 'timersOnly' are used as parameters. Status description contains additional details about the error.</p></td>
</tr>
</tbody>
</table>

## Users

### Get a single user

    GET identity/users/{userId}

<table>
<caption>Get a single user - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to get.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"testuser",
       "firstName":"Fred",
       "lastName":"McDonald",
       "url":"http://localhost:8182/identity/users/testuser",
       "email":"no-reply@flowable.org"
    }

<table>
<caption>Get a single user - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user exists and is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user does not exist.</p></td>
</tr>
</tbody>
</table>

### Get a list of users

    GET identity/users

<table>
<caption>Get a list of users - URL query parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>Only return user with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>firstName</p></td>
<td><p>Only return users with the given firstname</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>lastName</p></td>
<td><p>Only return users with the given lastname</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>email</p></td>
<td><p>Only return users with the given email</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>firstNameLike</p></td>
<td><p>Only return users with a firstname like the given value. Use % as wildcard-character.</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>lastNameLike</p></td>
<td><p>Only return users with a lastname like the given value. Use % as wildcard-character.</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>emailLike</p></td>
<td><p>Only return users with an email like the given value. Use % as wildcard-character.</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>memberOfGroup</p></td>
<td><p>Only return users which are a member of the given group.</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>potentialStarter</p></td>
<td><p>Only return users which are potential starters for a process-definition with the given id.</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>Field to sort results on, should be one of id, firstName, lastname or email.</p></td>
<td><p>String</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
          {
             "id":"anotherUser",
             "firstName":"Tijs",
             "lastName":"Barrez",
             "url":"http://localhost:8182/identity/users/anotherUser",
             "email":"no-reply@flowable.org"
          },
          {
             "id":"kermit",
             "firstName":"Kermit",
             "lastName":"the Frog",
             "url":"http://localhost:8182/identity/users/kermit",
             "email":null
          },
          {
             "id":"testuser",
             "firstName":"Fred",
             "lastName":"McDonald",
             "url":"http://localhost:8182/identity/users/testuser",
             "email":"no-reply@flowable.org"
          }
       ],
       "total":3,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":3
    }

<table>
<caption>Get a list of users - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the requested users were returned.</p></td>
</tr>
</tbody>
</table>

### Update a user

    PUT identity/users/{userId}

**Body JSON:**

    {
      "firstName":"Tijs",
      "lastName":"Barrez",
      "email":"no-reply@flowable.org",
      "password":"pass123"
    }

All request values are optional. For example, you can only include the 'firstName' attribute in the request body JSON-object, only updating the firstName of the user, leaving all other fields unaffected. When an attribute is explicitly included and is set to null, the user-value will be updated to null. Example: {"firstName" : null} will clear the firstName of the user).

<table>
<caption>Update a user - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user was updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found.</p></td>
</tr>
<tr class="odd">
<td><p>409</p></td>
<td><p>Indicates the requested user was updated simultaneously.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for identity/users/{userId}.

### Create a user

    POST identity/users

**Body JSON:**

    {
      "id":"tijs",
      "firstName":"Tijs",
      "lastName":"Barrez",
      "email":"no-reply@flowable.org",
      "password":"pass123"
    }

<table>
<caption>Create a user - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the user was created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the id of the user was missing.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for identity/users/{userId}.

### Delete a user

    DELETE identity/users/{userId}

<table>
<caption>Delete a user - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a user - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the user was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found.</p></td>
</tr>
</tbody>
</table>

### Get a user’s picture

    GET identity/users/{userId}/picture

<table>
<caption>Get a user’s picture - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to get the picture for.</p></td>
</tr>
</tbody>
</table>

**Response Body:**

The response body contains the raw picture data, representing the user’s picture. The Content-type of the response corresponds to the mimeType that was set when creating the picture.

<table>
<caption>Get a user’s picture - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user was found and has a picture, which is returned in the body.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found or the user does not have a profile picture. Status-description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Updating a user’s picture

    GET identity/users/{userId}/picture

<table>
<caption>Updating a user’s picture - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to get the picture for.</p></td>
</tr>
</tbody>
</table>

**Request body:**

The request should be of type multipart/form-data. There should be a single file-part included with the binary value of the picture. On top of that, the following additional form-fields can be present:

-   mimeType: Optional mime-type for the uploaded picture. If omitted, the default of image/jpeg is used as a mime-type for the picture.

<table>
<caption>Updating a user’s picture - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user was found and the picture has been updated. The response-body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found.</p></td>
</tr>
</tbody>
</table>

### List a user’s info

    PUT identity/users/{userId}/info

<table>
<caption>List a user’s info - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to get the info for.</p></td>
</tr>
</tbody>
</table>

**Response Body:**

    [
       {
          "key":"key1",
          "url":"http://localhost:8182/identity/users/testuser/info/key1"
       },
       {
          "key":"key2",
          "url":"http://localhost:8182/identity/users/testuser/info/key2"
       }
    ]

<table>
<caption>List a user’s info - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user was found and list of info (key and url) is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found.</p></td>
</tr>
</tbody>
</table>

### Get a user’s info

    GET identity/users/{userId}/info/{key}

<table>
<caption>Get a user’s info - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to get the info for.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The key of the user info to get.</p></td>
</tr>
</tbody>
</table>

**Response Body:**

    {
       "key":"key1",
       "value":"Value 1",
       "url":"http://localhost:8182/identity/users/testuser/info/key1"
    }

<table>
<caption>Get a user’s info - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user was found and the user has info for the given key..</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found or the user doesn’t have info for the given key. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Update a user’s info

    PUT identity/users/{userId}/info/{key}

<table>
<caption>Update a user’s info - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to update the info for.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The key of the user info to update.</p></td>
</tr>
</tbody>
</table>

**Request Body:**

    {
       "value":"The updated value"
    }

**Response Body:**

    {
       "key":"key1",
       "value":"The updated value",
       "url":"http://localhost:8182/identity/users/testuser/info/key1"
    }

<table>
<caption>Update a user’s info - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the user was found and the info has been updated.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the value was missing from the request body.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found or the user doesn’t have info for the given key. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

### Create a new user’s info entry

    POST identity/users/{userId}/info

<table>
<caption>Create a new user’s info entry - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to create the info for.</p></td>
</tr>
</tbody>
</table>

**Request Body:**

    {
       "key":"key1",
       "value":"The value"
    }

**Response Body:**

    {
       "key":"key1",
       "value":"The value",
       "url":"http://localhost:8182/identity/users/testuser/info/key1"
    }

<table>
<caption>Create a new user’s info entry - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the user was found and the info has been created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the key or value was missing from the request body. Status description contains additional information about the error.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates there is already an info-entry with the given key for the user, update the resource instance (PUT).</p></td>
</tr>
</tbody>
</table>

### Delete a user’s info

    DELETE identity/users/{userId}/info/{key}

<table>
<caption>Delete a user’s info - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to delete the info for.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The key of the user info to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a user’s info - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the user was found and the info for the given key has been deleted. Response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested user was not found or the user doesn’t have info for the given key. Status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

## Groups

### Get a single group

    GET identity/groups/{groupId}

<table>
<caption>Get a single group - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>groupId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the group to get.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "id":"testgroup",
       "url":"http://localhost:8182/identity/groups/testgroup",
       "name":"Test group",
       "type":"Test type"
    }

<table>
<caption>Get a single group - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the group exists and is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested group does not exist.</p></td>
</tr>
</tbody>
</table>

### Get a list of groups

    GET identity/groups

<table>
<caption>Get a list of groups - URL query parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Description</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>id</p></td>
<td><p>Only return group with the given id</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>name</p></td>
<td><p>Only return groups with the given name</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>type</p></td>
<td><p>Only return groups with the given type</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>nameLike</p></td>
<td><p>Only return groups with a name like the given value. Use % as wildcard-character.</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>member</p></td>
<td><p>Only return groups which have a member with the given username.</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td><p>potentialStarter</p></td>
<td><p>Only return groups which members are potential starters for a process-definition with the given id.</p></td>
<td><p>String</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>Field to sort results on, should be one of id, name or type.</p></td>
<td><p>String</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
       "data":[
         {
            "id":"testgroup",
            "url":"http://localhost:8182/identity/groups/testgroup",
            "name":"Test group",
            "type":"Test type"
         }
       ],
       "total":3,
       "start":0,
       "sort":"id",
       "order":"asc",
       "size":3
    }

<table>
<caption>Get a list of groups - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the requested groups were returned.</p></td>
</tr>
</tbody>
</table>

### Update a group

    PUT identity/groups/{groupId}

**Body JSON:**

    {
       "name":"Test group",
       "type":"Test type"
    }

All request values are optional. For example, you can only include the 'name' attribute in the request body JSON-object, only updating the name of the group, leaving all other fields unaffected. When an attribute is explicitly included and is set to null, the group-value will be updated to null.

<table>
<caption>Update a group - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the group was updated.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested group was not found.</p></td>
</tr>
<tr class="odd">
<td><p>409</p></td>
<td><p>Indicates the requested group was updated simultaneously.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for identity/groups/{groupId}.

### Create a group

    POST identity/groups

**Body JSON:**

    {
       "id":"testgroup",
       "name":"Test group",
       "type":"Test type"
    }

<table>
<caption>Create a group - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the group was created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates the id of the group was missing.</p></td>
</tr>
</tbody>
</table>

**Success response body:** see response for identity/groups/{groupId}.

### Delete a group

    DELETE identity/groups/{groupId}

<table>
<caption>Delete a group - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>groupId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the group to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a group - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the group was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested group was not found.</p></td>
</tr>
</tbody>
</table>

### Get members in a group

There is no GET allowed on identity/groups/members. Use the identity/users?memberOfGroup=sales URL to get all users that are part of a particular group.

### Add a member to a group

    POST identity/groups/{groupId}/members

<table>
<caption>Add a member to a group - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>groupId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the group to add a member to.</p></td>
</tr>
</tbody>
</table>

**Body JSON:**

    {
       "userId":"kermit"
    }

<table>
<caption>Add a member to a group - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the group was found and the member has been added.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the userId was not included in the request body.</p></td>
</tr>
<tr class="odd">
<td><p>404</p></td>
<td><p>Indicates the requested group was not found.</p></td>
</tr>
<tr class="even">
<td><p>409</p></td>
<td><p>Indicates the requested user is already a member of the group.</p></td>
</tr>
</tbody>
</table>

**Response Body:**

    {
       "userId":"kermit",
       "groupId":"sales",
        "url":"http://localhost:8182/identity/groups/sales/members/kermit"
    }

### Delete a member from a group

    DELETE identity/groups/{groupId}/members/{userId}

<table>
<caption>Delete a member from a group - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>groupId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the group to remove a member from.</p></td>
</tr>
<tr class="even">
<td><p>userId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The id of the user to remove.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a member from a group - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the group was found and the member has been deleted. The response body is left empty intentionally.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested group was not found or that the user is not a member of the group. The status description contains additional information about the error.</p></td>
</tr>
</tbody>
</table>

**Response Body:**

    {
       "userId":"kermit",
       "groupId":"sales",
        "url":"http://localhost:8182/identity/groups/sales/members/kermit"
    }

---

### Docusaurus Docs Bpmn Ch15 Cdi (`docs/docusaurus/docs/bpmn/ch15-Cdi.md`)

---
id: ch16-Cdi
title: CDI integration
---

The flowable-cdi modules leverages both the configurability of Flowable and the extensibility of cdi. The most prominent features of flowable-cdi are:

-   Support for @BusinessProcessScoped beans (CDI beans whose lifecycle is bound to a process instance),

-   A custom El-Resolver for resolving CDI beans (including EJBs) from the process,

-   Declarative control over a process instance using annotations,

-   Flowable is hooked-up to the CDI event bus,

-   Works with both Java EE and Java SE, works with Spring,

-   Support for unit testing.



    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-cdi</artifactId>
        <version>7.x</version>
    </dependency>

## Setting up flowable-cdi

Flowable-cdi can be set up in different environments. In this section we briefly walk through the configuration options.

### Looking up a Process Engine

The CDI extension needs to get access to a ProcessEngine. To achieve this, an implementation of the interface org.flowable.cdi.spi.ProcessEngineLookup is looked up at runtime. The CDI module ships with a default implementation named org.flowable.cdi.impl.LocalProcessEngineLookup, which uses the ProcessEngines-Utility class for looking up the ProcessEngine. In the default configuration ProcessEngines\#NAME\_DEFAULT is used to look up the ProcessEngine. This class might be subclassed to set a custom name. NOTE: You need a flowable.cfg.xml configuration on the classpath.

Flowable-cdi uses a java.util.ServiceLoader SPI for resolving an instance of org.flowable.cdi.spi.ProcessEngineLookup. In order to provide a custom implementation of the interface, we need to add a plain text file named META-INF/services/org.flowable.cdi.spi.ProcessEngineLookup to our deployment, in which we specify the fully qualified class name of the implementation.

> **Note**
>
> If you do not provide a custom org.flowable.cdi.spi.ProcessEngineLookup implementation, Flowable will use the default LocalProcessEngineLookup implementation. In that case, all you need to do is providing a flowable.cfg.xml file on the classpath (see next section).

### Configuring the Process Engine

Configuration depends on the selected ProcessEngineLookup-Strategy (cf. previous section). Here, we focus on the configuration options available in combination with the LocalProcessEngineLookup, which requires us to provide a Spring flowable.cfg.xml file on the classpath.

Flowable offers different ProcessEngineConfiguration implementations mostly dependent on the underlying transaction management strategy. The flowable-cdi module is not concerned with transactions, which means that potentially any transaction management strategy can be used (even the Spring transaction abstraction). As a convenience, the CDI module provides two custom ProcessEngineConfiguration implementations:

-   org.flowable.cdi.CdiJtaProcessEngineConfiguration: a subclass of the Flowable JtaProcessEngineConfiguration can be used if JTA-managed transactions should be used for Flowable

-   org.flowable.cdi.CdiStandaloneProcessEngineConfiguration: a subclass of the Flowable StandaloneProcessEngineConfiguration can be used if plain JDBC transactions should be used for Flowable. The following is an example flowable.cfg.xml file for JBoss 7:



    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

        
        <bean id="transactionManager" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:jboss/TransactionManager"></property>
            <property name="resourceRef" value="true" />
        </bean>

        
        <bean id="processEngineConfiguration"
            class="org.flowable.cdi.CdiJtaProcessEngineConfiguration">
            
            <property name="dataSourceJndiName" value="java:jboss/datasources/ExampleDS" />
            <property name="databaseType" value="h2" />
            <property name="transactionManager" ref="transactionManager" />
            
            <property name="transactionsExternallyManaged" value="true" />
            <property name="databaseSchemaUpdate" value="true" />
        </bean>
    </beans>

And this is how it would look like for Glassfish 3.1.1 (assuming a datasource named jdbc/flowable is properly configured):

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

        
        <bean id="transactionManager" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:appserver/TransactionManager"></property>
            <property name="resourceRef" value="true" />
        </bean>

        
        <bean id="processEngineConfiguration"
            class="org.flowable.cdi.CdiJtaProcessEngineConfiguration">
            <property name="dataSourceJndiName" value="jdbc/flowable" />
            <property name="transactionManager" ref="transactionManager" />
            
            <property name="transactionsExternallyManaged" value="true" />
            <property name="databaseSchemaUpdate" value="true" />
        </bean>
    </beans>

Note that the above configuration requires the "spring-context" module:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.5.RELEASE</version>
    </dependency>

The configuration in a Java SE environment looks exactly like the examples provided in section [Creating a ProcessEngine](bpmn/ch03-Configuration.md#creating-a-processengine), substitute CdiStandaloneProcessEngineConfiguration for StandaloneProcessEngineConfiguration.

### Deploying Processes

Processes can be deployed using the standard Flowable API (RepositoryService). In addition, flowable-cdi offers the possibility to auto-deploy processes listed in a file named processes.xml located top-level in the classpath. This is an example processes.xml file:

    <?xml version="1.0" encoding="utf-8" ?>
    
    <processes>
        <process resource="diagrams/myProcess.bpmn20.xml" />
        <process resource="diagrams/myOtherProcess.bpmn20.xml" />
    </processes>

## Contextual Process Execution with CDI

In this section we briefly look at the contextual process execution model used by the Flowable CDI extension. A BPMN business process is typically a long-running interaction, comprised of both user and system tasks. At runtime, a process is split-up into a set of individual units of work, performed by users and/or application logic. In flowable-cdi, a process instance can be associated with a CDI scope, the association representing a unit of work. This is particularly useful, if a unit of work is complex, for instance if the implementation of a user task is a complex sequence of different forms and "non-process-scoped" state needs to be kept during this interaction.

In the default configuration, process instances are associated with the "broadest" active scope, starting with the conversation and falling back to the request if the conversation context is not active.

### Associating a Conversation with a Process Instance

When resolving @BusinessProcessScoped beans, or injecting process variables, we rely on an existing association between an active CDI scope and a process instance. flowable-cdi provides the org.flowable.cdi.BusinessProcess bean for controlling the association, most prominently:

-   The *startProcessBy(…​)* methods, mirroring the respective methods exposed by the Flowable RuntimeService allowing to start and subsequently associating a business process.

-   resumeProcessById(String processInstanceId), allowing to associate the process instance with the provided id.

-   resumeTaskById(String taskId), allowing to associate the task with the provided id (and by extension, the corresponding process instance).

Once a unit of work (for example a user task) is completed, the completeTask() method can be called to disassociate the conversation/request from the process instance. This signals the engine that the current task is completed and makes the process instance proceed.

Note that the BusinessProcess bean is a @Named bean, which means that the exposed methods can be invoked using expression language, for example from a JSF page. The following JSF2 snippet begins a new conversation and associates it with a user task instance, the id of which is passed as a request parameter (e.g. pageName.jsf?taskId=XX):

    <f:metadata>
        <f:viewParam name="taskId" />
        <f:event type="preRenderView" listener="#{businessProcess.startTask(taskId, true)}" />
    </f:metadata>

### Declaratively controlling the Process

Flowable-cdi allows declaratively starting process instances and completing tasks using annotations. The @org.flowable.cdi.annotation.StartProcess annotation allows to start a process instance either by "key" or by "name". Note that the process instance is started *after* the annotated method returns. Example:

    @StartProcess("authorizeBusinessTripRequest")
    public String submitRequest(BusinessTripRequest request) {
        // do some work
        return "success";
    }

Depending on the configuration of Flowable, the code of the annotated method and the starting of the process instance will be combined in the same transaction. The @org.flowable.cdi.annotation.CompleteTask-annotation works in the same way:

    @CompleteTask(endConversation=false)
    public String authorizeBusinessTrip() {
        // do some work
        return "success";
    }

The @CompleteTask annotation offers the possibility to end the current conversation. The default behavior is to end the conversation after the call to Flowable returns. Ending the conversation can be disabled, as shown in the example above.

### Referencing Beans from the Process

Flowable-cdi exposes CDI beans to Flowable El, using a custom resolver. This makes it possible to reference beans from the process:

    <userTask id="authorizeBusinessTrip" name="Authorize Business Trip"
                flowable:assignee="#{authorizingManager.account.username}" />

Where authorizingManager could be a bean provided by a producer method:

    @Inject    @ProcessVariable Object businessTripRequesterUsername;

    @Produces
    @Named
    public Employee authorizingManager() {
        TypedQuery<Employee> query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.account.username='"
            + businessTripRequesterUsername + "'", Employee.class);
        Employee employee = query.getSingleResult();
        return employee.getManager();
    }

We can use the same feature to call a business method of an EJB in a service task, using the flowable:expression="myEjb.method()"-extension. Note that this requires a @Named-annotation on the MyEjb-class.

### Working with @BusinessProcessScoped beans

Using flowable-cdi, the lifecycle of a bean can be bound to a process instance. To this extent, a custom context implementation is provided, namely the BusinessProcessContext. Instances of BusinessProcessScoped beans are stored as process variables in the current process instance. BusinessProcessScoped beans need to be PassivationCapable (for example Serializable). The following is an example of a process scoped bean:

    @Named
    @BusinessProcessScoped
    public class BusinessTripRequest implements Serializable {
        private static final long serialVersionUID = 1L;
        private String startDate;
        private String endDate;
        // ...
    }

Sometimes, we want to work with process scoped beans, in the absence of an association with a process instance, for example before starting a process. If no process instance is currently active, instances of BusinessProcessScoped beans are temporarily stored in a local scope, i.e. the Conversation or the Request, depending on the context. If this scope is later associated with a business process instance, the bean instances are flushed to the process instance.

### Injecting Process Variables

Process variables are available for injection. flowable-cdi supports

-   type-safe injection of @BusinessProcessScoped beans using @Inject \\\[additional qualifiers\\\] Type fieldName

-   unsafe injection of other process variables using the @ProcessVariable(name?) qualifier:



    @Inject @ProcessVariable Object accountNumber;
    @Inject @ProcessVariable("accountNumber") Object account

In order to reference process variables using EL, there are similar options:

-   @Named @BusinessProcessScoped beans can be referenced directly,

-   other process variables can be referenced using the ProcessVariables-bean:



    #{processVariables['accountNumber']}

### Receiving Process Events

Flowable can be hooked-up to the CDI event bus. This allows us to be notified of process events using standard CDI event mechanisms. In order to enable CDI event support for Flowable, enable the corresponding parse listener in the configuration:

    <property name="postBpmnParseHandlers">
        <list>
            <bean class="org.flowable.cdi.impl.event.CdiEventSupportBpmnParseHandler" />
        </list>
    </property>

Now Flowable is configured for publishing events using the CDI event bus. The following gives an overview of how process events can be received in CDI beans. In CDI, we can declaratively specify event observers using the @Observes-annotation. Event notification is type-safe. The type of
process events is org.flowable.cdi.BusinessProcessEvent.
The following is an example of a simple event observer method:

    public void onProcessEvent(@Observes BusinessProcessEvent businessProcessEvent) {
        // handle event
    }

This observer would be notified of all events. If we want to restrict the set of events the observer receives, we can add qualifier annotations:

-   @BusinessProcess: restricts the set of events to a certain process definition. Example: @Observes @BusinessProcess("billingProcess") BusinessProcessEvent evt

-   @StartActivity: restricts the set of events by a certain activity. For example: @Observes @StartActivity("shipGoods") BusinessProcessEvent evt is invoke whenever an activity with the id "shipGoods" is entered.

-   @EndActivity: restricts the set of events by a certain activity. For example: @Observes @EndActivity("shipGoods") BusinessProcessEvent evt is invoke whenever an activity with the id "shipGoods" is left.

-   @TakeTransition: restricts the set of events by a certain transition.

-   @CreateTask: restricts the set of events by a certain task’s creation.

-   @DeleteTask: restricts the set of events by a certain task’s deletion.

-   @AssignTask: restricts the set of events by a certain task’s assignment.

-   @CompleteTask: restricts the set of events by a certain task’s completion.

The qualifiers named above can be combined freely. For example, in order to receive all events generated when leaving the "shipGoods" activity in the "shipmentProcess", we could write the following observer method:

    public void beforeShippingGoods(@Observes @BusinessProcess("shippingProcess") @EndActivity("shipGoods") BusinessProcessEvent evt) {
        // handle event
    }

In the default configuration, event listeners are invoked synchronously and in the context of the same transaction. CDI transactional observers (only available in combination with JavaEE/EJB), allow to control when the event is handed to the observer method. Using transactional observers, we can for example assure that an observer is only notified if the transaction in which the event is fired succeeds:

    public void onShipmentSucceeded(@Observes(during=TransactionPhase.AFTER_SUCCESS) @BusinessProcess("shippingProcess") @EndActivity("shipGoods") BusinessProcessEvent evt) {
        // send email to customer.
    }

### Additional Features

-   The ProcessEngine as well as the services are available for injection: @Inject ProcessEngine, RepositoryService, TaskService, …​

-   The current process instance and task can be injected: @Inject ProcessInstance, Task,

-   The current business key can be injected: @Inject @BusinessKey String businessKey,

-   The current process instance id be injected: @Inject @ProcessInstanceId String pid,

## Known Limitations

Although flowable-cdi is implemented against the SPI and designed to be a "portable-extension" it is only tested using Weld.

---

### Docusaurus Docs Bpmn Ch16 Ldap (`docs/docusaurus/docs/bpmn/ch16-Ldap.md`)

---
id: ch16-Ldap
title: LDAP integration
---

Companies often already have a user and group store in the form of an LDAP system. Flowable offers an out-of-the-box solution for easily configuring how Flowable should connect with an LDAP system.

In earlier versions, it was already possible to integrate LDAP, but since then, the configuration has been simplified a lot. However, the 'old' way of configuring LDAP still works. More specifically, the simplified configuration is just a wrapper on top of the 'old' infrastructure.

## Usage

To add the LDAP integration code to your project, simply add the following dependency to your pom.xml:

    <dependency>
      <groupId>org.flowable</groupId>
      <artifactId>flowable-ldap-configurator</artifactId>
      <version>latest.version</version>
    </dependency>

## Use cases

The LDAP integration has currently two main use cases:

-   Allow for authentication through the IdentityService. This could be useful when doing everything through the IdentityService.

-   Fetching the groups of a user. This is important when for example querying tasks to see which tasks a certain user can see (i.e. tasks with a candidate group).

## Configuration

Integrating the LDAP system with Flowable is done by injecting an instance of org.flowable.ldap.LDAPConfigurator in the idmProcessEngineConfigurator section of the process engine configuration. This class is highly extensible: methods can be easily overridden and many dependent beans are pluggable if the default implementation would not fit the use case.

This is an example configuration (note: of course, when creating the engine programmatically this is completely similar). Don’t worry about all the properties for now, we’ll look at them in detail in a next section.

    <bean id="processEngineConfiguration" class="...SomeProcessEngineConfigurationClass">
        ...
        <property name="idmProcessEngineConfigurator">
          <bean class="org.flowable.ldap.LDAPConfigurator">

            <property name="ldapConfiguration">
              <bean class="org.flowable.ldap.LDAPConfiguration">

                
                <property name="server" value="ldap://localhost" />
                <property name="port" value="33389" />
                <property name="user" value="uid=admin, ou=users, o=flowable" />
                <property name="password" value="pass" />

                
                <property name="baseDn" value="o=flowable" />
                <property name="queryUserByUserId" value="(&(objectClass=inetOrgPerson)(uid={0}))" />
                <property name="queryUserByFullNameLike" value="(&(objectClass=inetOrgPerson)(|({0}=*{1}*)({2}=*{3}*)))" />
                <property name="queryAllUsers" value="(objectClass=inetOrgPerson)" />
                <property name="queryGroupsForUser" value="(&(objectClass=groupOfUniqueNames)(uniqueMember={0}))" />
                <property name="queryAllGroups" value="(objectClass=groupOfUniqueNames)" />

                
                <property name="userIdAttribute" value="uid" />
                <property name="userFirstNameAttribute" value="cn" />
                <property name="userLastNameAttribute" value="sn" />
                <property name="userEmailAttribute" value="mail" />

                <property name="groupIdAttribute" value="cn" />
                <property name="groupNameAttribute" value="cn" />

              </bean>
            </property>
          </bean>
        </property>
    </bean>

## Properties

Following properties can be set on org.flowable.ldap.LDAPConfiguration:

    .LDAP configuration properties

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Property name</th>
<th>Description</th>
<th>Type</th>
<th>Default value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>server</p></td>
<td><p>The server on which the LDAP system can be reached. For example 'ldap://localhost:33389'</p></td>
<td><p>String</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>port</p></td>
<td><p>The port on which the LDAP system is running</p></td>
<td><p>int</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>user</p></td>
<td><p>The user id that is used to connect to the LDAP system</p></td>
<td><p>String</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>password</p></td>
<td><p>The password that is used to connect to the LDAP system</p></td>
<td><p>String</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>initialContextFactory</p></td>
<td><p>The InitialContextFactory name used to connect to the LDAP system</p></td>
<td><p>String</p></td>
<td><p>com.sun.jndi.ldap.LdapCtxFactory</p></td>
</tr>
<tr class="even">
<td><p>securityAuthentication</p></td>
<td><p>The value that is used for the 'java.naming.security.authentication' property used to connect to the LDAP system</p></td>
<td><p>String</p></td>
<td><p>simple</p></td>
</tr>
<tr class="odd">
<td><p>customConnectionParameters</p></td>
<td><p>Allows to set all LDAP connection parameters which do not have a dedicated setter.
See for example <a href="http://docs.oracle.com/javase/tutorial/jndi/ldap/jndi.html">http://docs.oracle.com/javase/tutorial/jndi/ldap/jndi.html</a> for custom
properties. Such properties are for example to configure connection pooling, specific
security settings, etc. All the provided parameters will be provided when creating a
connection to the LDAP system.</p></td>
<td><p>Map&lt;String, String&gt;</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>baseDn</p></td>
<td><p>The base 'distinguished name' (DN) from which the searches for users and groups are started</p></td>
<td><p>String</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>userBaseDn</p></td>
<td><p>The base 'distinguished name' (DN) from which the searches for users are started. If not provided, baseDn (see above) will be used</p></td>
<td><p>String</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>groupBaseDn</p></td>
<td><p>The base 'distinguished name' (DN) from which the searches for groups are started. If not provided, baseDn (see above) will be used</p></td>
<td><p>String</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>searchTimeLimit</p></td>
<td><p>The timeout that is used when doing a search in LDAP in milliseconds</p></td>
<td><p>long</p></td>
<td><p>one hour</p></td>
</tr>
<tr class="even">
<td><p>queryUserByUserId</p></td>
<td><p>The query that is executed when searching for a user by userId.
For example: (&amp;(objectClass=inetOrgPerson)(uid={0}))
Here, all the objects in LDAP with the class 'inetOrgPerson'
and who have the matching 'uid' attribute value will be returned.
As shown in the example, the user id is injected by using
{0}. If setting the query alone is insufficient for your specific
LDAP setup, you can alternatively plug in a different
LDAPQueryBuilder, which allows for more customization than only the query.</p></td>
<td><p>string</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>queryUserByFullNameLike</p></td>
<td><p>The query that is executed when searching for a user by full name.
For example: (&amp; (objectClass=inetOrgPerson) (</p></td>
<td><p>({0}=<strong>{1}</strong>)({2}=<strong>{3}</strong>)) )
Here, all the objects in LDAP with the class 'inetOrgPerson'
and who have the matching first name and last name values will be returned.
Note that {0} injects the firstNameAttribute (as defined above), {1} and {3} the search text
and {2} the lastNameAttribute. If setting the query alone is insufficient for your specific
LDAP setup, you can alternatively plug in a different
LDAPQueryBuilder, which allows for more customization than only the query.</p></td>
<td><p>string</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>queryAllUsers</p></td>
<td><p>The query that is executed when searching on users without a filter.
For example: (objectClass=inetOrgPerson)
Here, all the objects in LDAP with the class 'inetOrgPerson' will be returned.</p></td>
<td><p>string</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>queryGroupsForUser</p></td>
<td><p>The query that is executed when searching for the groups of a specific user.
For example: (&amp;(objectClass=groupOfUniqueNames)(uniqueMember={0}))
Here, all the objects in LDAP with the class 'groupOfUniqueNames'
and where the provided DN (matching a DN for a user) is a 'uniqueMember' are returned.
As shown in the example, the user id is injected by using {0}
If setting the query alone is insufficient for your specific
LDAP setup, you can alternatively plug in a different
LDAPQueryBuilder, which allows for more customization than only the query.</p></td>
<td><p>string</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>queryAllGroups</p></td>
<td><p>The query that is executed when searching on groups without a filter.
For example: (objectClass=groupOfUniqueNames)
Here, all the objects in LDAP with the class 'groupOfUniqueNames' will be returned.</p></td>
<td><p>string</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>userIdAttribute</p></td>
<td><p>Name of the attribute that matches the user id.
This property is used when looking for a User object
and the mapping between the LDAP object and the Flowable User object
is done.</p></td>
<td><p>string</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>userFirstNameAttribute</p></td>
<td><p>Name of the attribute that matches the user first name.
This property is used when looking for a User object
and the mapping between the LDAP object and the Flowable User object is done.</p></td>
<td><p>string</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>userLastNameAttribute</p></td>
<td><p>Name of the attribute that matches the user last name.
This property is used when looking for a User object
and the mapping between the LDAP object and the Flowable User object is done.</p></td>
<td><p>string</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>groupIdAttribute</p></td>
<td><p>Name of the attribute that matches the group id.
This property is used when looking for a Group object
and the mapping between the LDAP object and the Flowable Group object is done.</p></td>
<td><p>string</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>groupNameAttribute</p></td>
<td><p>Name of the attribute that matches the group name.
This property is used when looking for a Group object
and the mapping between the LDAP object and the Flowable Group object is done.</p></td>
<td><p>String</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>groupTypeAttribute</p></td>
<td><p>Name of the attribute that matches the group type.
This property is used when looking for a Group object
and the mapping between the LDAP object and the Flowable Group object
is done.</p></td>
<td><p>String</p></td>
</tr>
</tbody>
</table>

Following properties are when one wants to customize default behavior or introduced group caching:

<table>
<caption>Advanced properties</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Property name</th>
<th>Description</th>
<th>Type</th>
<th>Default value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>ldapUserManagerFactory</p></td>
<td><p>Set a custom implementation of the LDAPUserManagerFactory if the default implementation is not suitable.</p></td>
<td><p>instance of LDAPUserManagerFactory</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>ldapGroupManagerFactory</p></td>
<td><p>Set a custom implementation of the LDAPGroupManagerFactory if the default implementation is not suitable.</p></td>
<td><p>instance of LDAPGroupManagerFactory</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>ldapMemberShipManagerFactory</p></td>
<td><p>Set a custom implementation of the LDAPMembershipManagerFactory if the default implementation is not suitable.
Note that this is very unlikely, as membership are managed in the LDAP system itself normally.</p></td>
<td><p>An instance of LDAPMembershipManagerFactory</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>ldapQueryBuilder</p></td>
<td><p>Set a custom query builder if the default implementation is not suitable.
The LDAPQueryBuilder instance is used when the LDAPUserManager or
LDAPGroupManage} does an actual query against the LDAP system.
The default implementation uses the properties as set on this instance
such as queryGroupsForUser and queryUserById</p></td>
<td><p>An instance of org.flowable.ldap.LDAPQueryBuilder</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>groupCacheSize</p></td>
<td><p>Allows to set the size of the group cache.
This is an LRU cache that caches groups for users and thus
avoids hitting the LDAP system each time the groups of
a user needs to be known.</p>
<p>The cache will not be instantiated if the value is less than zero.
By default set to -1, so no caching is done.</p></td>
<td><p>int</p></td>
<td><p>-1</p></td>
</tr>
<tr class="even">
<td><p>groupCacheExpirationTime</p></td>
<td><p>Sets the expiration time of the group cache in milliseconds.
When groups for a specific user are fetched, and if the group cache exists,
the groups will be stored in this cache for the time set in this property.
I.e. when the groups were fetched at 00:00 and the expiration time is 30 minutes,
any fetch of the groups for that user after 00:30 will not come from the cache, but do
a fetch again from the LDAP system. Likewise, everything group fetch for that user done
between 00:00 - 00:30 will come from the cache.</p></td>
<td><p>long</p></td>
<td><p>one hour</p></td>
</tr>
</tbody>
</table>

Note when using Active Directory: people have reported that for Active Directory, the 'InitialDirContext' needs to be set to Context.REFERRAL. This can be passed through the customConnectionParameters map as described above.

---

### Docusaurus Docs Bpmn Ch17 Advanced (`docs/docusaurus/docs/bpmn/ch17-Advanced.md`)

---
id: ch18-Advanced
title: Advanced
---

The following sections cover advanced use cases of Flowable, that go beyond typical execution of BPMN 2.0 processes. As such, a certain proficiency and experience with Flowable is advised to understand the topics described here.

## Async Executor

### Async Executor design

Two types of jobs exist: timers (such as those belonging to a boundary event on a user task) and async continuations (belonging to a service task with the *flowable:async="true"* attribute).

**Timers** are the easiest to explain: they are persisted in the ACT\_RU\_TIMER\_JOB table with a certain due date. There is a thread in the async executor that periodically checks if there are new timers that should fire (in other words, the due date is 'before' the current time). When that happens, the timer is removed and an async job is created.

An **async job** is inserted in the database during the execution of process instance steps (which means, during some API call that was made). If the async executor is active for the current Flowable engine, the async job is actually already *locked*. This means that the job entry is inserted in the ACT\_RU\_JOB table and will have a *lock owner* and a *lock expiration time* set. A transaction listener that fires on a successful commit of the API call triggers the async executor of the same engine to execute the job (so the data is guaranteed to be in the database). To do this, the async executor has a configurable thread pool from which a thread will execute the job and continue the process asynchronously. If the Flowable engine does not have the async executor enabled, the async job is inserted in the ACT\_RU\_JOB table without being locked.

Similar to the thread that checks for new timers, the async executor has a thread that 'acquires' new async jobs. These are jobs that are present in the table that are not locked. This thread will lock these jobs for the current Flowable engine and pass it to the async executor.

The thread pool executing the jobs uses an in-memory queue from which to take jobs. When this queue is full (this is configurable), the job will be unlocked and re-inserted into its table. This way, other async executors can pick it up instead.

If an exception happens during job execution, the async job will be transformed to a timer job with a due date. Later, it will be picked up like a regular timer job and become an async job again, to be retried soon. When a job has been retried for a (configurable) number of times and continues to fail, the job is assumed to be 'dead' and moved to the ACT\_RU\_DEADLETTER\_JOB. The 'deadletter' concept is widely used in various other systems. An administrator will now need to inspect the exception for the failed job and decide what the best course of action is.

Process definitions and process instances can be suspended. Suspended jobs related to these definitions or instances are put in the ACT\_RU\_SUSPENDED\_JOB table, to make sure the query to acquire jobs has as few possible conditions in its where clause.

One thing that is clear from the above: for people familiar with the old implementations of the job/async executor, the main goal is to allow the 'acquire queries' to be as simple as possible. In the past (before V6), one table was used for all job types/states, which made the 'where' condition large as it catered for all the use cases. This problem is now solved and our benchmarks have proved that this new design delivers better performance and is more scalable.

### Async executor configuration

The async executor is a highly configurable component. It’s always recommended to look into the default settings of the async executor and validate if they match the requirements of your processes.

Alternatively, it’s possible to extend the default implementation or replace the *org.flowable.engine.impl.asyncexecutor.AsyncExecutor* interface with your own implementation.

The following properties are available on the process engine configuration through setters:

<table>
<caption>Async executor configuration options</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Name</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>asyncExecutorThreadPoolQueueSize</p></td>
<td><p>100</p></td>
<td><p>The size of the queue on which jobs to be executed are placed after being acquired, before they are actually executed by a thread from the thread pool</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorCorePoolSize</p></td>
<td><p>8</p></td>
<td><p>The minimal number of threads that are kept alive in the thread pool for job execution.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorMaxPoolSize</p></td>
<td><p>8</p></td>
<td><p>The maximum number of threads that are created in the thread pool for job execution.</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorThreadKeepAliveTime</p></td>
<td><p>5000</p></td>
<td><p>The time (in milliseconds) a thread used for job execution must be kept alive before it is destroyed. Having a setting &gt; 0 takes resources, but in the case of many job executions it avoids creating new threads all the time. If 0, threads will be destroyed after they’ve been used for job execution.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorNumberOfRetries</p></td>
<td><p>3</p></td>
<td><p>The number of times a job will be retried before it is moved to the 'deadletter' table.</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorMaxTimerJobsPerAcquisition</p></td>
<td><p>1</p></td>
<td><p>The number of timer jobs that are acquired in one query. Default value is 1, as this lowers the potential for optimistic locking exceptions. Larger values can perform better, but the chance of optimistic locking exceptions occurring between different engines becomes larger too.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorMaxAsyncJobsDuePerAcquisition</p></td>
<td><p>1</p></td>
<td><p>The number of async jobs that are acquired during one query. Default value is 1, as this lowers the potential for optimistic locking exceptions. Larger values can perform better, but the chance of optimistic locking exceptions occurring between different engines becomes larger too.</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorDefaultTimerJobAcquireWaitTime</p></td>
<td><p>10000</p></td>
<td><p>The time (in milliseconds) the timer acquisition thread will wait to execute the next query. This happens when no new timer jobs are found or when less timer jobs have been fetched than set in <em>asyncExecutorMaxTimerJobsPerAcquisition</em>.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorDefaultAsyncJobAcquireWaitTime</p></td>
<td><p>10000</p></td>
<td><p>The time (in milliseconds) the async job acquisition thread will wait to execute the next query. This happens when no new async jobs were found or when less async jobs have been fetched than set in <em>asyncExecutorMaxAsyncJobsDuePerAcquisition</em>.</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorDefaultQueueSizeFullWaitTime</p></td>
<td><p>0</p></td>
<td><p>The time (in milliseconds) the async job (both timer and async continuations) acquisition thread will wait when the internal job queue is full to execute the next query. By default set to 0 (for backwards compatibility). Setting this property to a higher value allows the async executor to hopefully clear its queue a bit.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorTimerLockTimeInMillis</p></td>
<td><p>5 minutes</p></td>
<td><p>The amount of time (in milliseconds) a timer job is locked when acquired by the async executor. During this period of time, no other async executor will try to acquire and lock this job.</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorAsyncJobLockTimeInMillis</p></td>
<td><p>5 minutes</p></td>
<td><p>The amount of time (in milliseconds) an async job is locked when acquired by the async executor. During this period of time, no other async executor will try to acquire and lock this job.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorSecondsToWaitOnShutdown</p></td>
<td><p>60</p></td>
<td><p>The time (in seconds) that is waited to gracefully shut down the thread pool used for job execution when a shutdown on the executor (or process engine) is requested.</p></td>
</tr>
<tr class="even">
<td><p>asyncExecutorResetExpiredJobsInterval</p></td>
<td><p>60 seconds</p></td>
<td><p>The amount of time (in milliseconds) that is between two consecutive checks of 'expired jobs'. Expired jobs are jobs that were locked (a lock owner + time was written by some executor, but the job was never completed). During such a check, jobs that are expired are made available again, meaning the lock owner and lock time will be removed. Other executors will now be able to pick it up. A job is deemed expired if the lock time is before the current date.</p></td>
</tr>
<tr class="odd">
<td><p>asyncExecutorResetExpiredJobsPageSize</p></td>
<td><p>3</p></td>
<td><p>The amount of jobs that are fetched at once by the 'reset expired' thread of the async executor.</p></td>
</tr>
</tbody>
</table>

## Hooking into process parsing

A BPMN 2.0 XML needs to be parsed to the Flowable internal model to be executed on the Flowable engine. This parsing happens during a deployment of the process or when a process is not found in memory, and the XML is fetched from the database.

For each of these processes, the BpmnParser class creates a new BpmnParse instance. This instance will be used as container for all things that are done during parsing. The parsing, by itself, is very simple: for each BPMN 2.0 element, there is a matching instance of the org.flowable.engine.parse.BpmnParseHandler available in the engine. As such, the parser has a map that basically maps a BPMN 2.0 element class to an instance of BpmnParseHandler. By default, Flowable has BpmnParseHandler instances to handle all supported elements and also uses it to attach execution listeners to steps of the process for creating the history.

It is possible to add custom instances of org.flowable.engine.parse.BpmnParseHandler to the Flowable engine. An often seen use case, for example, is to add execution listeners to certain steps that fire events to some queue for event processing. The history handling is done in such a way internally in Flowable. To add such custom handlers, the Flowable configuration needs to be tweaked:

    <property name="preBpmnParseHandlers">
      <list>
        <bean class="org.flowable.parsing.MyFirstBpmnParseHandler" />
      </list>
    </property>

    <property name="postBpmnParseHandlers">
      <list>
        <bean class="org.flowable.parsing.MySecondBpmnParseHandler" />
        <bean class="org.flowable.parsing.MyThirdBpmnParseHandler" />
      </list>
    </property>

The list of BpmnParseHandler instances that is configured in the preBpmnParseHandlers property are added before any of the default handlers. Likewise, the postBpmnParseHandlers are added after those. This can be important if the order of things matter for the logic contained in the custom parse handlers.

org.flowable.engine.parse.BpmnParseHandler is a simple interface:

    public interface BpmnParseHandler {

      Collection<Class>? extends BaseElement>> getHandledTypes();

      void parse(BpmnParse bpmnParse, BaseElement element);

    }

The getHandledTypes() method returns a collection of all the types handled by this parser. The possible types are a subclass of BaseElement, as directed by the generic type of the collection. You can also extend the AbstractBpmnParseHandler class and override the getHandledType() method, which only returns one Class and not a collection. This class also contains some helper methods shared by many of the default parse handlers. The BpmnParseHandler instance will be called when the parser encounters any of the types returned by this method. In the following example, whenever a process contained in some BPMN 2.0 XML is encountered, it will execute the logic in the executeParse method (which is a typecast method that replaces the regular parse method on the BpmnParseHandler interface).

    public class TestBPMNParseHandler extends AbstractBpmnParseHandler<Process> {

      protected Class<? extends BaseElement> getHandledType() {
        return Process.class;
      }

      protected void executeParse(BpmnParse bpmnParse, Process element) {
         ..
      }

    }

**Important note:** when writing custom parse handlers, do not use any of the internal classes that are used to parse the BPMN 2.0 constructs. This will cause difficult to find bugs. The safe way to implement a custom handler is to implement the *BpmnParseHandler* interface or extend the internal abstract class *org.flowable.engine.impl.bpmn.parser.handler.AbstractBpmnParseHandler*.

It is possible (but less common) to replace the default BpmnParseHandler instances that are responsible for the parsing of the BPMN 2.0 elements to the internal Flowable model. This can be done by following snippet of logic:

    <property name="customDefaultBpmnParseHandlers">
      <list>
        ...
      </list>
    </property>

A simple example could, for example, be to force all of the service tasks to be asynchronous:

    public class CustomUserTaskBpmnParseHandler extends ServiceTaskParseHandler {

      protected void executeParse(BpmnParse bpmnParse, ServiceTask serviceTask) {

        // Do the regular stuff
        super.executeParse(bpmnParse, serviceTask);

        // Make always async
        serviceTask.setAsynchronous(true);
      }

    }

## UUID ID generator for high concurrency

In some (very) high concurrency load cases, the default ID generator may cause exceptions due to not being able to fetch new ID blocks quickly enough. Every process engine has one ID generator. The default ID generator reserves a block of IDs in the database, such that no other engine will be able to use IDs from the same block. During engine operations, when the default ID generator notices that the ID block is used up, a new transaction is started to fetch a new block. In (very) limited use cases this can cause problems when there is a real high load. For most use cases the default ID generator is more than sufficient. The default org.flowable.engine.impl.db.DbIdGenerator also has a property idBlockSize which can be configured to set the size of the reserved block of IDs and to tweak the behavior of the ID fetching.

The alternative to the default ID generator is the org.flowable.engine.impl.persistence.StrongUuidGenerator, which generates a unique [UUID](http://en.wikipedia.org/wiki/Universally_unique_identifier) locally and uses that as an identifier for all entities. Since the UUID is generated without the need for database access, it copes better with very high concurrency use cases. Do note that performance may differ from the default ID generator (both positive and negative) depending on the machine.

The UUID generator can be set up in the Flowable configuration as follows:

    <property name="idGenerator">
        <bean class="org.flowable.engine.impl.persistence.StrongUuidGenerator" />
    </property>

The use of the UUID ID generator has the following extra dependency:

     <dependency>
        <groupId>com.fasterxml.uuid</groupId>
        <artifactId>java-uuid-generator</artifactId>
        <version>3.1.3</version>
    </dependency>

## Multitenancy

Multitenancy in general is a concept where the software is capable of serving multiple different organizations. Key is that the data is partitioned and no organization can see the data of other ones. In this context, such an organization (or a department, or a team or whatever, is called a *tenant*.

Note that this is fundamentally different from a multi-instance setup, where a Flowable Process engine instance is running for each organization separately (and with a different database schema). Although Flowable is lightweight, and running a Process Engine instance doesn’t take much resources, it does add complexity and more maintenance. But, for some use cases it might be the right solution.

Multitenancy in Flowable is mainly implemented around partitioning the data. It is important to note that *Flowable does not enforce multi tenancy rules*. This means it will not verify when querying and using data whether the user doing the operation belongs to the correct tenant. This should be done in the layer calling the Flowable engine. Flowable does make sure that tenant information can be stored and used when retrieving process data.

When deploying process definition to the Flowable Process engine it is possible to pass a *tenant identifier*. This is a string (e.g. a UUID, department id, etc.), limited to 256 characters which uniquely identifies the tenant:

    repositoryService.createDeployment()
                .addClassPathResource(...)
                .tenantId("myTenantId")
                .deploy();

Passing a tenant ID during a deployment has following implications:

-   All the process definitions contained in the deployment inherit the tenant identifier from this deployment.

-   All process instances started from those process definitions inherit this tenant identifier from the process definition.

-   All tasks created at runtime when executing the process instance inherit this tenant identifier from the process instance. Standalone tasks can have a tenant identifier too.

-   All executions created during process instance execution inherit this tenant identifier from the process instance.

-   Firing a signal throw event (in the process itself or through the API) can be done whilst providing a tenant identifier. The signal will only be executed in the tenant context: i.e. if there are multiple signal catch events with the same name, only the one with the correct tenant identifier will actually be called.

-   All jobs (timers and async continuations) inherit the tenant identifier from either the process definition (e.g. timer start event) or the process instance (when a job is created at runtime, e.g. an async continuation). This could potentially be used for giving priority to some tenants in a custom job executor.

-   All the historic entities (historic process instance, task and activities) inherit the tenant identifier from their runtime counterparts.

-   As a side note, models can have a tenant identifier too (models are used e.g. by the Flowable modeler to store BPMN 2.0 models).

To actually make use of the tenant identifier on the process data, all the query API’s have the capability to filter on tenant. For example (and can be replaced by the relevant query implementation of the other entities):

    runtimeService.createProcessInstanceQuery()
        .processInstanceTenantId("myTenantId")
        .processDefinitionKey("myProcessDefinitionKey")
        .variableValueEquals("myVar", "someValue")
        .list()

The query API’s also allow to filter on the tenant identifier with *like* semantics and also to filter out entities without tenant id.

**Important implementation detail:** due to database quirks (more specifically: null handling in unique constraints) the *default* tenant identifier value indicating *no tenant* is the **empty string**. The combination of (process definition key, process definition version, tenant identifier) needs to be unique (and there is a database constraint checking this). Also note that the tenant identifier shouldn’t be set to null, as this will affect the queries since certain databases (Oracle) treat empty string as a null value (that’s why the query *.withoutTenantId* does a check against the empty string or null). This means that the same process definition (with same process definition key) can be deployed for multiple tenants, each with their own versioning. This does not affect the usage when tenancy is not used.

**Do note that all of the above does not conflict with running multiple Flowable instances in a cluster.**

\[Experimental\] It is possible to change the tenant identifier by calling the *changeDeploymentTenantId(String deploymentId, String newTenantId)* method on the *repositoryService*. This will change the tenant identifier everywhere it was inherited before. This can be useful when going from a non-multitenant setup to a multitenant configuration. See the Javadoc on the method for more detailed information.

## Execute custom SQL

The Flowable API allows for interacting with the database using a high level API. For example, for retrieving data the Query API and the Native Query API are powerful in its usage. However, for some use cases they might not be flexible enough. The following section describes how a completely custom SQL statement (select, insert, update and delete are possible) can be executed against the Flowable data store, but completely within the configured Process Engine (and thus levering the transaction setup for example).

To define custom SQL statements, the Flowable engine leverages the capabilities of its underlying framework, MyBatis. More info can be read [in the MyBatis user guide](http://mybatis.github.io/mybatis-3/java-api.html).

### Annotation based Mapped Statements

The first thing to do when using Annotation based Mapped Statements, is to create a MyBatis mapper class. For example, suppose that for some use case not the whole task data is needed, but only a small subset of it. A Mapper that could do this, looks as follows:

    public interface MyTestMapper {

        @Select("SELECT ID_ as id, NAME_ as name, CREATE_TIME_ as createTime FROM ACT_RU_TASK")
        List<Map<String, Object>> selectTasks();

    }

This mapper must be provided to the Process Engine configuration as follows:

    ...
    <property name="customMybatisMappers">
      <set>
        <value>org.flowable.standalone.cfg.MyTestMapper</value>
      </set>
    </property>
    ...

Notice that this is an interface. The underlying MyBatis framework will make an instance of it that can be used at runtime. Also notice that the return value of the method is not typed, but a list of maps (which corresponds to the list of rows with column values). Typing is possible with the MyBatis mappers if wanted.

To execute the query above, the *managementService.executeCustomSql* method must be used. This method takes in a *CustomSqlExecution* instance. This is a wrapper that hides the internal bits of the engine otherwise needed to make it work.

Unfortunately, Java generics make it a bit less readable than it could have been. The two generic types below are the mapper class and the return type class. However, the actual logic is simply to call the mapper method and return its results (if applicable).

    CustomSqlExecution<MyTestMapper, List<Map<String, Object>>> customSqlExecution =
              new AbstractCustomSqlExecution<MyTestMapper, List<Map<String, Object>>>(MyTestMapper.class) {

      public List<Map<String, Object>> execute(MyTestMapper customMapper) {
        return customMapper.selectTasks();
      }

    };

    List<Map<String, Object>> results = managementService.executeCustomSql(customSqlExecution);

The Map entries in the list above will only contain *id, name and create time* in this case and not the full task object.

Any SQL is possible when using the approach above. Another more complex example:

        @Select({
            "SELECT task.ID_ as taskId, variable.LONG_ as variableValue FROM ACT_RU_VARIABLE variable",
            "inner join ACT_RU_TASK task on variable.TASK_ID_ = task.ID_",
            "where variable.NAME_ = #{variableName}"
        })
        List<Map<String, Object>> selectTaskWithSpecificVariable(String variableName);

Using this method, the task table will be joined with the variables table. Only where the variable has a certain name is retained, and the task id and the corresponding numerical value is returned.

For a working example on using Annotation based Mapped Statements check the unit test *org.flowable.standalone.cfg.CustomMybatisMapperTest* and other classes and resources in folders src/test/java/org/flowable/standalone/cfg/ and src/test/resources/org/flowable/standalone/cfg/

### XML based Mapped Statements

When using XML based Mapped Statements, statements are defined in XML files. For the use case where not the whole task data is needed, but only a small subset of it. The XML file can look as follows:

    <mapper namespace="org.flowable.standalone.cfg.TaskMapper">

      <resultMap id="customTaskResultMap" type="org.flowable.standalone.cfg.CustomTask">
        <id property="id" column="ID_" jdbcType="VARCHAR"/>
        <result property="name" column="NAME_" jdbcType="VARCHAR"/>
        <result property="createTime" column="CREATE_TIME_" jdbcType="TIMESTAMP" />
      </resultMap>

      <select id="selectCustomTaskList" resultMap="customTaskResultMap">
        select RES.ID_, RES.NAME_, RES.CREATE_TIME_ from ACT_RU_TASK RES
      </select>

    </mapper>

Results are mapped to instances of *org.flowable.standalone.cfg.CustomTask* class which can look as follows:

    public class CustomTask {

      protected String id;
      protected String name;
      protected Date createTime;

      public String getId() {
        return id;
      }
      public String getName() {
        return name;
      }
      public Date getCreateTime() {
        return createTime;
      }
    }

Mapper XML files must be provided to the Process Engine configuration as follows:

    ...
    <property name="customMybatisXMLMappers">
      <set>
        <value>org/flowable/standalone/cfg/custom-mappers/CustomTaskMapper.xml</value>
      </set>
    </property>
    ...

The statement can be executed as follows:

    List<CustomTask> tasks = managementService.executeCommand(new Command<List<CustomTask>>() {

          @SuppressWarnings("unchecked")
          @Override
          public List<CustomTask> execute(CommandContext commandContext) {
            return (List<CustomTask>) CommandContextUtil.getDbSqlSession().selectList("selectCustomTaskList");
          }
        });

For uses cases that require more complicated statements, XML Mapped Statements can be helpful. Since Flowable uses XML Mapped Statements internally, it’s possible to make use of the underlying capabilities.

Suppose that for some use case the ability to query attachments data is required based on id, name, type, userId, etc! To fulfill the use case a query class *AttachmentQuery* that extends *org.flowable.engine.impl.AbstractQuery* can be created as follows:

    public class AttachmentQuery extends AbstractQuery<AttachmentQuery, Attachment> {

      protected String attachmentId;
      protected String attachmentName;
      protected String attachmentType;
      protected String userId;

      public AttachmentQuery(ManagementService managementService) {
        super(managementService);
      }

      public AttachmentQuery attachmentId(String attachmentId){
        this.attachmentId = attachmentId;
        return this;
      }

      public AttachmentQuery attachmentName(String attachmentName){
        this.attachmentName = attachmentName;
        return this;
      }

      public AttachmentQuery attachmentType(String attachmentType){
        this.attachmentType = attachmentType;
        return this;
      }

      public AttachmentQuery userId(String userId){
        this.userId = userId;
        return this;
      }

      @Override
      public long executeCount(CommandContext commandContext) {
        return (Long) CommandContextUtil.getDbSqlSession()
                       .selectOne("selectAttachmentCountByQueryCriteria", this);
      }

      @Override
      public List<Attachment> executeList(CommandContext commandContext, Page page) {
        return CommandContextUtil.getDbSqlSession()
                .selectList("selectAttachmentByQueryCriteria", this);
      }

Note that when extending *AbstractQuery* extended classes should pass an instance of *ManagementService* to super constructor and methods *executeCount* and *executeList* need to be implemented to call the mapped statements.

The XML file containing the mapped statements can look as follows:

    <mapper namespace="org.flowable.standalone.cfg.AttachmentMapper">

      <select id="selectAttachmentCountByQueryCriteria" parameterType="org.flowable.standalone.cfg.AttachmentQuery" resultType="long">
        select count(distinct RES.ID_)
        <include refid="selectAttachmentByQueryCriteriaSql"/>
      </select>

      <select id="selectAttachmentByQueryCriteria" parameterType="org.flowable.standalone.cfg.AttachmentQuery" resultMap="org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap">
        ${limitBefore}
        select distinct RES.* ${limitBetween}
        <include refid="selectAttachmentByQueryCriteriaSql"/>
        ${orderBy}
        ${limitAfter}
      </select>

      <sql id="selectAttachmentByQueryCriteriaSql">
      from ${prefix}ACT_HI_ATTACHMENT RES
      <where>
       <if test="attachmentId != null">
         RES.ID_ = #{attachmentId}
       </if>
       <if test="attachmentName != null">
         and RES.NAME_ = #{attachmentName}
       </if>
       <if test="attachmentType != null">
         and RES.TYPE_ = #{attachmentType}
       </if>
       <if test="userId != null">
         and RES.USER_ID_ = #{userId}
       </if>
      </where>
      </sql>
    </mapper>

Capabilities such as pagination, ordering, table name prefixing are available and can be used in the statements (since the parameterType is a subclass of *AbstractQuery*). Note that to map results the predefined *org.flowable.engine.impl.persistence.entity.AttachmentEntity.attachmentResultMap* resultMap can be used.

Finally, the *AttachmentQuery* can be used as follows:

    ....
    // Get the total number of attachments
    long count = new AttachmentQuery(managementService).count();

    // Get attachment with id 10025
    Attachment attachment = new AttachmentQuery(managementService).attachmentId("10025").singleResult();

    // Get first 10 attachments
    List<Attachment> attachments = new AttachmentQuery(managementService).listPage(0, 10);

    // Get all attachments uploaded by user kermit
    attachments = new AttachmentQuery(managementService).userId("kermit").list();
    ....

For working examples on using XML Mapped Statements check the unit test *org.flowable.standalone.cfg.CustomMybatisXMLMapperTest* and other classes and resources in folders src/test/java/org/flowable/standalone/cfg/ and src/test/resources/org/flowable/standalone/cfg/

## Advanced Process Engine configuration with a ProcessEngineConfigurator

An advanced way of hooking into the process engine configuration is through the use of a *ProcessEngineConfigurator*. The idea is that an implementation of the *org.flowable.engine.cfg.ProcessEngineConfigurator* interface is created and injected into the process engine configuration:

    <bean id="processEngineConfiguration" class="...SomeProcessEngineConfigurationClass">

        ...

        <property name="configurators">
            <list>
                <bean class="com.mycompany.MyConfigurator">
                    ...
                </bean>
            </list>
        </property>

        ...

    </bean>

There are two methods required to implement this interface. The *configure* method, which gets a *ProcessEngineConfiguration* instance as parameter. The custom configuration can be added this way, and this method will guaranteed be called **before the process engine is created, but after all default configuration has been done**. The other method is the *getPriority* method, which allows for ordering the configurators in the case where some configurators are dependent on each other.

An example of such a configurator is the [LDAP integration](bpmn/ch16-Ldap.md#ldap-integration), where the configurator is used to replace the default user and group manager classes with one that is capable of handling an LDAP user store. So basically a configurator allows to change or tweak the process engine quite heavily and is meant for very advanced use cases. Another example is to swap the process definition cache with a customized version:

    public class ProcessDefinitionCacheConfigurator extends AbstractProcessEngineConfigurator {

        public void configure(ProcessEngineConfigurationImpl processEngineConfiguration) {
                MyCache myCache = new MyCache();
                processEngineConfiguration.setProcessDefinitionCache(enterpriseProcessDefinitionCache);
        }

    }

Process Engine configurators can also be auto discovered from the classpath using the [ServiceLoader](http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html) approach. This means that a jar with the configurator implementation must be put on the classpath, containing a file in the *META-INF/services* folder in the jar called **org.flowable.engine.cfg.ProcessEngineConfigurator**. The content of the file needs to be the fully qualified classname of the custom implementation. When the process engine is booted, the logging will show that these configurators are found:

    INFO  org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl  - Found 1 auto-discoverable Process Engine Configurators
    INFO  org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl  - Found 1 Process Engine Configurators in total:
    INFO  org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl  - class org.flowable.MyCustomConfigurator

Note that this ServiceLoader approach might not work in certain environments. It can be explicitly disabled using the *enableConfiguratorServiceLoader* property of the ProcessEngineConfiguration (true by default).

## Advanced query API: seamless switching between runtime and historic task querying

One core component of any BPM user interface is the task list. Typically, end users work on open, runtime tasks, filtering their inbox with various setting. Often also the historic tasks need to be displayed in those lists, with similar filtering. To make that code-wise easier, the *TaskQuery* and *HistoricTaskInstanceQuery* both have a shared parent interface, which contains all common operations (and most of the operations are common).

This common interface is the *org.flowable.engine.task.TaskInfoQuery* class. Both *org.flowable.engine.task.Task* and *org.flowable.engine.task.HistoricTaskInstance* have a common superclass *org.flowable.engine.task.TaskInfo* (with common properties) which is returned from e.g. the *list()* method. However, Java generics are sometimes more harming than helping: if you want to use the *TaskInfoQuery* type directly, it would look like this:

    TaskInfoQuery<? extends TaskInfoQuery<?,?>, ? extends TaskInfo> taskInfoQuery

Ugh, Right. To 'solve' this, a *org.flowable.engine.task.TaskInfoQueryWrapper* class that can be used to avoid the generics (the following code could come from REST code that returns a task list where the user can switch between open and completed tasks):

    TaskInfoQueryWrapper taskInfoQueryWrapper = null;
    if (runtimeQuery) {
        taskInfoQueryWrapper = new TaskInfoQueryWrapper(taskService.createTaskQuery());
    } else {
        taskInfoQueryWrapper = new TaskInfoQueryWrapper(historyService.createHistoricTaskInstanceQuery());
    }

    List<? extends TaskInfo> taskInfos = taskInfoQueryWrapper.getTaskInfoQuery().or()
        .taskNameLike("%k1%")
        .taskDueAfter(new Date(now.getTime() + (3 * 24L * 60L * 60L * 1000L)))
    .endOr()
    .list();

## Custom identity management by overriding standard SessionFactory

If you do not want to use a full *ProcessEngineConfigurator* implementation like in the [LDAP integration](bpmn/ch16-Ldap.md#ldap-integration), but still want to plug in your custom identity management framework, then you can also override the *IdmIdentityServiceImpl* class or implement the *IdmIdentityService* interface directly and use the implemented class for the *idmIdentityService* property in the *ProcessEngineConfiguration*. In Spring this can be easily done by adding the following to the *ProcessEngineConfiguration* bean definition:

    <bean id="processEngineConfiguration" class="...SomeProcessEngineConfigurationClass">

        ...

        <property name="idmIdentityService">
            <bean class="com.mycompany.IdmIdentityServiceBean"/>
        </property>

        ...

    </bean>

Have a look at the *LDAPIdentityServiceImpl* class implementation to have a good example of how to implement the methods of the *IdmIdentityService* interface.
You have to figure out which methods you want to implement in the custom identity service class. For example the following call:

    long potentialOwners = identityService.createUserQuery().memberOfGroup("management").count();

leads to a call on the following member of the *IdmIdentityService* interface:

    UserQuery createUserQuery();

The code for the [LDAP integration](bpmn/ch16-Ldap.md#ldap-integration) contains full examples of how to implement this. Check out the code on Github: [LDAPIdentityServiceImpl](https://github.com/flowable/flowable-engine/blob/master/modules/flowable-ldap/src/main/java/org/flowable/ldap/LDAPIdentityServiceImpl.java).

## Enable safe BPMN 2.0 xml

In most cases the BPMN 2.0 processes that are being deployed to the Flowable engine are under tight control of e.g. the development team. However, in some use cases it might be desirable to upload arbitrary BPMN 2.0 xml to the engine. In that case, take into consideration that a user with bad intentions can bring the server down as described [here](http://www.jorambarrez.be/blog/2013/02/19/uploading-a-funny-xml-can-bring-down-your-server/).

To avoid the attacks described in the link above, a property *enableSafeBpmnXml* can be set on the process engine configuration:

    <property name="enableSafeBpmnXml" value="true"/>

**By default this feature is disabled!** The reason for this is that it relies on the availability of the StaxSource class of the JDK. Unfortunately, on some platforms this class is unavailable (due to older xml parser implementation) and thus the safe BPMN 2.0 xml feature cannot be enabled.

If the platform on which Flowable runs does support it, do enable this feature.

## Event logging

An event logging mechanism has been introduced. The logging mechanism builds upon the general-purpose [event mechanism of the Flowable engine](bpmn/ch03-Configuration.md#event-handlers) and is disabled by default. The idea is that the events originating from the engine are caught, and a map containing all the event data (and some more) is created and provided to an *org.flowable.engine.impl.event.logger.EventFlusher* which will flush this data to somewhere else. By default, simple database-backed event handlers/flusher is used, which serializes the said map to JSON using Jackson and stores it in the database as an *EventLogEntryEntity* instance. The table required for this database logging is created by default (called *ACT\_EVT\_LOG*). This table can be deleted if the event logging is not used.

To enable the database logger:

    processEngineConfigurationImpl.setEnableDatabaseEventLogging(true);

or at runtime:

    databaseEventLogger = new EventLogger(processEngineConfiguration.getClock(),
                                          processEngineConfiguration.getObjectMapper());
    runtimeService.addEventListener(databaseEventLogger);

The EventLogger class can be extended. In particular, the *createEventFlusher()* method needs to return an instance of the *org.flowable.engine.impl.event.logger.EventFlusher* interface if the default database logging is not wanted. The *managementService.getEventLogEntries(startLogNr, size);* can be used to retrieve the *EventLogEntryEntity* instances through Flowable.

It is easy to see how this table data can now be used to feed the JSON into a big data NoSQL store such as MongoDB, Elastic Search, etc. It is also easy to see that the classes used here (org.flowable.engine.impl.event.logger.EventLogger/EventFlusher and many EventHandler classes) are pluggable and can be tweaked to your own use case (eg not storing the JSON in the database, but firing it straight onto a queue or big data store).

Note that this event logging mechanism is additional to the 'traditional' history manager of Flowable. Although all the data is in the database tables,
it is not optimized for querying nor for easy retrieval. The real use case is audit trailing and feeding it into a big data store.

## Disabling bulk inserts

By default, the engine will group multiple insert statements for the same database table together in a *bulk insert*, thus improving performance. This has been tested and implemented for all supported databases.

However, it could be a specific version of a supported and tested database does not allow bulk inserts (we have for example a report for DB2 on z/OS, although DB2 in general works), the bulk insert can be disabled on the process engine configuration:

    <property name="bulkInsertEnabled" value="false" />

## Secure Scripting

By default, when using a [script task](bpmn/ch07b-BPMN-Constructs.md#script-Task), the script that is executed has similar capabilities as a Java delegate. It has full access to the JVM, can run forever (due to infinite loops) or use up a lot of memory. However, Java delegates need to be written and put on the classpath in a jar and they have a different life cycle from a process definitions. End-users generally will not write Java delegates, as this is a typical the job of a developer.

Scripts on the other hand are part of the process definition and its lifecycle is the same. Script tasks don’t need the extra step of a jar deployment, but can be executed from the moment the process definition is deployed. Sometimes, scripts for script tasks are not written by developers. Yet, this poses a problem as stated above: a script has full access to the JVM and it is possible to block many system resources when executing the script. Allowing scripts from just about anyone is thus not a good idea.

To solve this problem, the *secure scripting* feature can be enabled. Currently, this feature is implemented for *javascript* scripting only. To enable it, add the *flowable-secure-javascript* dependency to your project. When using maven:

    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-secure-javascript</artifactId>
        <version>${flowable.version}</version>
    </dependency>

Adding this dependency will transitively bring in the Rhino dependency (see [<https://github.com/mozilla/rhino>]($https://github.com/mozilla/rhino$$)). Rhino is a javascript engine for the JDK. It used to be included in JDK version 6 and 7 and was superseded by the Nashorn engine. However, the Rhino project continued development after it was included in the JDK. Many features (including the ones Flowable uses to implement the secure scripting) were added afterwards. At the time of writing, the Nashorn engine **does not** have the features that are needed to implement the secure scripting feature.

This does mean that there could be (typically small) differences between scripts (for example, *importPackage* works on Rhino, but *load()* has to be used on Nashorn).

Configuring the secure scripting is done through a dedicated *Configurator* object that is passed to the process engine configuration before the process engine is instantiated:

    SecureJavascriptConfigurator configurator = new SecureJavascriptConfigurator()
      .setWhiteListedClasses(new HashSet<String>(Arrays.asList("java.util.ArrayList")))
      .setMaxStackDepth(10)
      .setMaxScriptExecutionTime(3000L)
      .setMaxMemoryUsed(3145728L)
      .setNrOfInstructionsBeforeStateCheckCallback(10);

    processEngineConfig.addConfigurator(configurator);

Following settings are possible:

-   **enableClassWhiteListing**: When true, all classes will be blacklisted and all classes that want to be used will need to be whitelisted individually. This gives tight control over what is exposed to scripts. By default *false*.

-   **whiteListedClasses**: a Set of Strings corresponding with fully qualified classnames of the classes that are allowed to be used in the script. For example, to expose the *execution* object in a script, the *org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl* String needs to be added to this Set. By default *empty*.

-   **maxStackDepth**: Limits the stack depth while calling functions within a script. This can be used to avoid stack overflow exceptions that occur when recursively calling a method defined in the script. By default *-1* (disabled).

-   **maxScriptExecutionTime**: The maximum time a script is allowed to run. By default *-1* (disabled).

-   **maxMemoryUsed**: The maximum memory, in bytes, that the script is allowed to use. Note that the script engine itself takes a a certain amount of memory that is counted here too. By default *-1* (disabled).

-   **nrOfInstructionsBeforeStateCheckCallback**: The maximum script execution time and memory usage is implemented using a callback that is called every x instructions of the script. Note that these are not script instructions, but Java byte code instructions (which means one script line could be hundreds of byte code instructions). By default 100.

*Note:* the *maxMemoryUsed* setting can only be used by a JVM that supports the com.sun.management.ThreadMXBean\#getThreadAllocatedBytes() method. The Oracle JDK has this.

There is also a secure variant of the ScriptExecutionListener and ScriptTaskListener: *org.flowable.scripting.secure.listener.SecureJavascriptExecutionListener* and *org.flowable.scripting.secure.listener.SecureJavascriptTaskListener*.

It’s used as follows:

    <flowable:executionListener event="start" class="org.flowable.scripting.secure.listener.SecureJavascriptExecutionListener">
      <flowable:field name="script">
        <flowable:string>
            <![CDATA[
                execution.setVariable('test');
            ]]>
        </flowable:string>
      </flowable:field>
      <flowable:field name="language" stringValue="javascript" />
    </flowable:executionListener>

For examples that demonstrate unsecure scripts and how they are made secure by the *secure scripting* feature, please check the [unit tests on Github](https://github.com/Flowable/Flowable/tree/main/modules/flowable-secure-javascript/src/test/resources)

## Logging Sessions \[Experimental\]

Added in 6.5.0, Logging sessions allow you to collect information about process execution even if an exception causes the transaction to be rolled back.  This is enabled by providing a LoggingListener implementation to the engine configuration.  The loggingListener contains a single method called `loggingGenerated` that takes a list of Jackson ObjectNodes.  


In this simple implementation, each ObjectNode is sent to the logger:

```
class MyLoggingListener implements LoggingListener{
    static Logger logger = LoggerFactory.getLogger(MyLoggingListener.class);
    
    @Override
    public void loggingGenerated(List<ObjectNode> loggingNodes) {
        loggingNodes.forEach(jsonNodes -> logger.info(jsonNodes.toString()));
    }
}
```

During process engine configuration, an instance of the LoggingListener is passed 

```
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
      .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
      .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
      .setLoggingListener(new MyLoggingListener())
      .buildProcessEngine();

```

### LoggingSession ObjectNodes
 
 The list of ObjectNodes passed to loggingGenerated method Are JSON objects, with at least the following attributes:
 - `message` - a human readable message
 - `scopeId` - a correlation ID to group all messages from the same transaction 
 - `scopeType` - the type of the scope
 
 Additional fields will also be present based on the type of event they describe:
 
```
2020-01-21 10:46:54.852  INFO 4985 --- [  restartedMain] c.e.f.MyLoggingListener                : {"message":"Variable 'initiator' created","scopeId":"a193efb3-3c6d-11ea-a01d-bed6c476b3ed","scopeType":"bpmn","variableName":"initiator","variableType":"null","variableRawValue":null,"variableValue":null,"scopeDefinitionId":"loggingSessionProcess:1:a18d38ef-3c6d-11ea-a01d-bed6c476b3ed","scopeDefinitionKey":"loggingSessionProcess","scopeDefinitionName":"Logging Session Process","__id":"a1948bf5-3c6d-11ea-a01d-bed6c476b3ed","__timeStamp":"2020-01-21T16:46:54.819Z","type":"variableCreate","__transactionId":"a1948bf5-3c6d-11ea-a01d-bed6c476b3ed","__logNumber":1}
```

---

### Docusaurus Docs Bpmn Ch18 Tooling (`docs/docusaurus/docs/bpmn/ch18-tooling.md`)

---
id: ch18-tooling
title: Tooling
---

## JMX

### Introduction

It is possible to connect to Flowable engine using standard Java Management Extensions (JMX) technology in order to get information or to change its behavior. Any standard JMX client can be used for that purpose. Enabling and disabling Job Executor, deploy new process definition files and deleting them are just samples of what could be done using JMX without writing a single line of code.

### Quick Start

By default JMX is not enabled. To enable JMX in its default configuration, it is enough to add the flowable-jmx jar file to your classpath, using Maven or by any other means. In case you are using Maven, you can add proper dependency by adding the following lines in your pom.xml:

    <dependency>
      <groupId>org.flowable</groupId>
      <artifactId>flowable-jmx</artifactId>
      <version>latest.version</version>
    </dependency>

After adding the dependency and building process engine, the JMX connection is ready to be used. Just run jconsole available in a standard JDK distribution. In the list of local processes, you will see the JVM containing Flowable. If for any reason the proper JVM is not listed in "local processes" section, try connecting to it using this URL in "Remote Process" section:

    service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi/flowable

You can find the exact local URL in your log files. After connecting, you can see the standard JVM statistics and MBeans. You can view Flowable specific MBeans by selecting MBeans tab and select "org.flowable.jmx.Mbeans" on the right panel. By selecting any MBean, you can query information or change configuration. This snapshot shows how the jconsole looks like:

Any JMX client not limited to jconsole can be used to access MBeans. Most of data center monitoring tools have some connectors which enables them to connect to JMX MBeans.

### Attributes and operations

Here is a list available attributes and operations at this moment. This list may extend in future releases based on needs.

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>MBean</th>
<th>Type</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>ProcessDefinitionsMBean</p></td>
<td><p>Attribute</p></td>
<td><p>processDefinitions</p></td>
<td><p>Id, Name, Version, IsSuspended properties of deployed process definitions as a list of list of Strings</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>Attribute</p></td>
<td><p>deployments</p></td>
<td><p>Id, Name, TenantId properties of current deployments</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>method</p></td>
<td><p>getProcessDefinitionById(String id)</p></td>
<td><p>Id, Name, Version and IsSuspended properties of the process definition with given id</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>method</p></td>
<td><p>deleteDeployment(String id)</p></td>
<td><p>Deletes deployment with the given Id</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>method</p></td>
<td><p>suspendProcessDefinitionById(String id)</p></td>
<td><p>Suspends the process definition with the given Id</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>method</p></td>
<td><p>activatedProcessDefinitionById(String id)</p></td>
<td><p>Activates the process definition with the given Id</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>method</p></td>
<td><p>suspendProcessDefinitionByKey(String id)</p></td>
<td><p>Suspends the process definition with the given key</p></td>
</tr>
<tr class="even">
<td></td>
<td><p>method</p></td>
<td><p>activatedProcessDefinitionByKey(String id)</p></td>
<td><p>Activates the process definition with the given key</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>method</p></td>
<td><p>deployProcessDefinition(String resourceName, String processDefinitionFile)</p></td>
<td><p>Deploys the process definition file</p></td>
</tr>
<tr class="even">
<td><p>JobExecutorMBean</p></td>
<td><p>attribute</p></td>
<td><p>isJobExecutorActivated</p></td>
<td><p>Returns true if the async job executor is activated, false otherwise</p></td>
</tr>
<tr class="odd">
<td></td>
<td><p>method</p></td>
<td><p>setJobExecutorActivate(Boolean active)</p></td>
<td><p>Activates and Deactivates the async job executor based on the given boolean</p></td>
</tr>
</tbody>
</table>

### Configuration

JMX uses default configuration to make it easy to deploy with the most used configuration. However it is easy to change the default configuration. You can do it programmatically or via configuration file. The following code excerpt shows how this could be done in the configuration file:

    <bean id="processEngineConfiguration" class="...SomeProcessEngineConfigurationClass">
      ...
      <property name="configurators">
        <list>
          <bean class="org.flowable.management.jmx.JMXConfigurator">

            <property name="connectorPort" value="1912" />
            <property name="serviceUrlPath" value="/jmxrmi/flowable" />

            ...
          </bean>
        </list>
      </property>
    </bean>

This table shows what parameters you can configure along with their default values:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Name</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>disabled</p></td>
<td><p>false</p></td>
<td><p>if set, JMX will not be started even in presence of the dependency</p></td>
</tr>
<tr class="even">
<td><p>domain</p></td>
<td><p>org.flowable.jmx.Mbeans</p></td>
<td><p>Domain of MBean</p></td>
</tr>
<tr class="odd">
<td><p>createConnector</p></td>
<td><p>true</p></td>
<td><p>if true, creates a connector for the started MbeanServer</p></td>
</tr>
<tr class="even">
<td><p>MBeanDomain</p></td>
<td><p>DefaultDomain</p></td>
<td><p>domain of MBean server</p></td>
</tr>
<tr class="odd">
<td><p>registryPort</p></td>
<td><p>1099</p></td>
<td><p>appears in the service URL as registry port</p></td>
</tr>
<tr class="even">
<td><p>serviceUrlPath</p></td>
<td><p>/jmxrmi/flowable</p></td>
<td><p>appears in the service URL</p></td>
</tr>
<tr class="odd">
<td><p>connectorPort</p></td>
<td><p>-1</p></td>
<td><p>if greater than zero, will appear in service URL as connector port</p></td>
</tr>
</tbody>
</table>

### JMX Service URL

The JMX service URL has the following format:

    service:jmx:rmi://<hostName>:<connectorPort>/jndi/rmi://<hostName>:<registryPort>/<serviceUrlPath>

hostName will be automatically set to the network name of the machine.
connectorPort, registryPort and serviceUrlPath can be configured.

If connectionPort is less than zero, the corresponding part of service URL will be dropped and it will be simplified to:

    service:jmx:rmi:///jndi/rmi://:<hostname>:<registryPort>/<serviceUrlPath>

## Maven archetypes

### Create Test Case

During development, sometimes it is helpful to create a small test case to test an idea or a feature,
before implementing it in the real application.
This helps to isolate the subject under test. JUnit test cases are also the preferred tools for communicating
bug reports and feature requests.
Having a test case attached to a bug report or feature request jira issue, considerably reduces its fixing time.

To facilitate creation of a test case, a maven archetype is available. By use of this archetype, one can rapidly create a standard test case.
The archetype should be already available in the standard repository. If not, you can easily install it in your local maven repository folder by just typing
**mvn install** in **tooling/archtypes** folder.

The following command creates the unit test project:

    mvn archetype:generate \
    -DarchetypeGroupId=org.flowable \
    -DarchetypeArtifactId=flowable-archetype-unittest \
    -DarchetypeVersion=<current version> \
    -DgroupId=org.myGroup \
    -DartifactId=myArtifact

The effect of each parameter is explained in the following table:

<table>
<caption>Unittest Generation archetype parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<tbody>
<tr class="odd">
<td><p>Row</p></td>
<td><p>Parameter</p></td>
<td><p>Explanation</p></td>
</tr>
<tr class="even">
<td><p>1</p></td>
<td><p>archetypeGroupId</p></td>
<td><p>Group id of the archetype. should be <strong>org.flowable</strong></p></td>
</tr>
<tr class="odd">
<td><p>2</p></td>
<td><p>archetypeArtifactId</p></td>
<td><p>Artifact if of the archetype. should be <strong>flowable-archetype-unittest</strong></p></td>
</tr>
<tr class="even">
<td><p>3</p></td>
<td><p>archetypeVersion</p></td>
<td><p>Flowable version used in the generated test project</p></td>
</tr>
<tr class="odd">
<td><p>4</p></td>
<td><p>groupId</p></td>
<td><p>Group id of the generated test project</p></td>
</tr>
<tr class="even">
<td><p>5</p></td>
<td><p>artifactId</p></td>
<td><p>Artifact id of the generated test project</p></td>
</tr>
</tbody>
</table>

The directory structure of the generated project would be like this:

    .
    ├── pom.xml
    └── src
        └── test
            ├── java
            │   └── org
            │       └── myGroup
            │           └── MyUnitTest.java
            └── resources
                ├── flowable.cfg.xml
                ├── log4j.properties
                └── org
                    └── myGroup
                        └── my-process.bpmn20.xml

You can modify the Java unit test case and its corresponding process model, or add new test cases and process models.
If you are using the project to articulate a bug or a feature, test case should fail initially. It should then pass
after the desired bug is fixed or the desired feature is implemented.
Please make sure to clean the project by typing **mvn clean** before sending it.

---

### Docusaurus Docs Cmmn Ch02 Configuration (`docs/docusaurus/docs/cmmn/ch02-Configuration.md`)

---
id: ch02-Configuration
title: Configuration
---

## Creating a CmmnEngine

The Flowable CMMN engine is configured through an XML file called flowable.cmmn.cfg.xml. Note that this is **not** applicable if you’re using [the Spring style of building a process engine](cmmn/ch04-Spring.md#spring-integration).

The easiest way to obtain a CmmnEngine is to use the org.flowable.cmmn.engine.CmmnEngineConfiguration class:

    CmmnEngine cmmnEngine = CmmnEngineConfiguration.createStandaloneCmmnEngineConfiguration();

This will look for a flowable.cmmn.cfg.xml file on the classpath and construct an engine based on the configuration in that file. The following snippet shows an example configuration. The following sections will give a detailed overview of the configuration properties.

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.engine.CmmnEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="jdbcDriver" value="org.h2.Driver" />
        <property name="jdbcUsername" value="sa" />
        <property name="jdbcPassword" value="" />

        <property name="databaseSchemaUpdate" value="true" />
      </bean>

    </beans>

Note that the configuration XML is in fact a Spring configuration. **This does not mean that Flowable can only be used in a Spring environment!** We are simply leveraging the parsing and dependency injection capabilities of Spring internally for building up the engine.

The CmmnEngineConfiguration object can also be created programmatically using the configuration file. It is also possible to use a different bean id (for example, see line 3).

    CmmnEngineConfiguration.
      createCmmnEngineConfigurationFromResourceDefault();
      createCmmnEngineConfigurationFromResource(String resource);
      createCmmnEngineConfigurationFromResource(String resource, String beanName);
      createCmmnEngineConfigurationFromInputStream(InputStream inputStream);
      createCmmnEngineConfigurationFromInputStream(InputStream inputStream, String beanName);

It is also possible not to use a configuration file, and create a configuration based on
defaults (see [the different supported classes](#configurationClasses) for more information).

    CmmnEngineConfiguration.createStandaloneCmmnEngineConfiguration();
    CmmnEngineConfiguration.createStandaloneInMemCmmnEngineConfiguration();

All these CmmnEngineConfiguration.createXXX() methods return a CmmnEngineConfiguration that can be tweaked further if needed. After calling the buildCmmnEngine() operation, a CmmnEngine is created:

    CmmnEngine cmmnEngine = CmmnEngineConfiguration.createStandaloneInMemCmmnEngineConfiguration()
      .setDatabaseSchemaUpdate(CmmnEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
      .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
      .buildCmmnEngine();

## CmmnEngineConfiguration bean

The flowable.cmmn.cfg.xml must contain a bean that has the id 'cmmnEngineConfiguration'.

     <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.engine.CmmnEngineConfiguration">

This bean is then used to construct the CmmnEngine. There are multiple classes available that can be used to define the cmmnEngineConfiguration. These classes represent different environments, and set defaults accordingly. It is a best practice to select the class that best matches your environment, to minimize the number of properties needed to configure the engine. The following classes are currently available:
<a name="configurationClasses"></a>

-   **org.flowable.cmmn.engine.impl.cfg.StandaloneInMemCmmnEngineConfiguration**: this is a convenience class for unit testing purposes. Flowable will take care of all transactions. An H2 in-memory database is used by default. The database will be created and dropped when the engine boots and shuts down. When using this, no additional configuration is probably needed.

-   **org.flowable.cmmn.spring.SpringCmmnEngineConfiguration**: To be used when the CMMN engine is used in a Spring environment. See [the Spring integration section](cmmn/ch04-Spring.md#spring-integration) for more information.

## Database configuration

There are two ways to configure the database that the Flowable CMMN engine will use. The first option is to define the JDBC properties of the database:

-   **jdbcUrl**: JDBC URL of the database.

-   **jdbcDriver**: implementation of the driver for the specific database type.

-   **jdbcUsername**: username to connect to the database.

-   **jdbcPassword**: password to connect to the database.

The data source that is constructed based on the provided JDBC properties will have the default [MyBatis](http://www.mybatis.org/) connection pool settings. The following attributes can optionally be set to tweak that connection pool (taken from the MyBatis documentation):

-   **jdbcMaxActiveConnections**: The number of active (i.e., in use) connections that the exist at any given time. Default is 10.

-   **jdbcMaxIdleConnections**: The number of idle connections that the exist at any given time.

-   **jdbcMaxCheckoutTime**: The amount of time in milliseconds that a connection can be 'checked out' of the connection pool before it is forcefully returned. Default is 20000. (20 seconds).

-   **jdbcMaxWaitTime**: This is a low level setting that gives the pool a chance to print a log status and re-attempt the acquisition of a connection in the case that it is taking unusually long (to avoid failing silently forever if the pool is misconfigured). Default is 20000. (20 seconds).

Example database configuration:

    <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />

Our benchmarks have shown that the MyBatis connection pool is not the most efficient or resilient when dealing with a lot of concurrent requests. As such, it is advised to use a javax.sql.DataSource implementation and inject it into the process engine configuration (For example HikariCP, Tomcat JDBC Connection Pool, etc.):

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/flowable" />
      <property name="username" value="flowable" />
      <property name="password" value="flowable" />
      <property name="defaultAutoCommit" value="false" />
    </bean>

    <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.engine.CmmnEngineConfiguration">

      <property name="dataSource" ref="dataSource" />
      ...

Note that Flowable does not ship with a library that allows you to define such a data source. So you need to make sure that the libraries are on your classpath.

The following properties can be set, regardless of whether you are using the JDBC or data source approach:

-   **databaseType**: it’s normally not necessary to specify this property, as it is automatically detected from the database connection metadata. Should only be specified when automatic detection fails. Possible values: {h2, mysql, oracle, postgres, mssql, db2}. This setting will determine which create/drop scripts and queries will be used. See [the 'supported databases' section](cmmn/ch02-Configuration.md#supported-databases) for an overview of which types are supported.

-   **databaseSchemaUpdate**: sets the strategy to handle the database schema on process engine boot and shutdown.

    -   false (default): Checks the version of the DB schema against the library when the process engine is being created and throws an exception if the versions don’t match.

    -   true: Upon building the process engine, a check is performed and an update of the schema is performed if it is necessary. If the schema doesn’t exist, it is created.

    -   create-drop: Creates the schema when the process engine is being created and drops the schema when the process engine is being closed.

## JNDI Datasource Configuration

By default, the database configuration for Flowable is contained within the db.properties files in the WEB-INF/classes of each web application. This isn’t always ideal because it
requires users to either modify the db.properties in the Flowable source and recompile the WAR file, or explode the WAR and modify the db.properties on every deployment.

By using JNDI (Java Naming and Directory Interface) to obtain the database connection, the connection is fully managed by the Servlet Container and the configuration can be managed outside the WAR deployment. This also allows more control over the connection parameters than what is provided by the db.properties file.

### Configuration

Configuration of the JNDI data source will differ depending on what servlet container application you are using. The instructions below will work for Tomcat, but for other container applications, please refer to the documentation for your container app.

If using Tomcat, the JNDI resource is configured within $CATALINA\_BASE/conf/\[enginename\]/\[hostname\]/\[warname\].xml (for the Flowable UI this will usually be $CATALINA\_BASE/conf/Catalina/localhost/flowable-app.xml). The default context is copied from the Flowable WAR file when the application is first deployed, so if it already exists, you will need to replace it. To change the JNDI resource so that the application connects to MySQL instead of H2, for example, change the file to the following:

    <?xml version="1.0" encoding="UTF-8"?>
        <Context antiJARLocking="true" path="/flowable-app">
            <Resource auth="Container"
                name="jdbc/flowableDB"
                type="javax.sql.DataSource"
                description="JDBC DataSource"
                url="jdbc:mysql://localhost:3306/flowable"
                driverClassName="com.mysql.jdbc.Driver"
                username="sa"
                password=""
                defaultAutoCommit="false"
                initialSize="5"
                maxWait="5000"
                maxActive="120"
                maxIdle="5"/>
            </Context>

### JNDI properties

To configure a JNDI data source, use the following properties in the properties file for the Flowable UI:

-   spring.datasource.jndi-name=: the JNDI name of the data source.

-   datasource.jndi.resourceRef: Set whether the lookup occurs in a J2EE container, for example, the prefix "java:comp/env/" needs to be added if the JNDI name doesn’t already contain it. Default is "true".

### Custom properties

System properties can also be used in the flowable.cmmn.cfg.xml by using them in the format `${propertyName:defaultValue}`.

    <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
    <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
    <property name="jdbcUsername" value="${jdbc.username:sa}" />
    <property name="jdbcPassword" value="${jdbc.password:}" />

Using this configuration if the property `jdbc.url` is available then it would be used for the `jdbcUrl` of the `CmmnEngineConfiguration`.
Otherwise the value after the first `:` would be used.

It is also possible to define locations from where properties can be picked up from the system by using a bean of type org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.

Example configuration with custom location for properties

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/opt/conf/flowable.properties" />
      </bean>

      <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.engine.CmmnEngineConfiguration">

        <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
        <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
        <property name="jdbcUsername" value="${jdbc.username:sa}" />
        <property name="jdbcPassword" value="${jdbc.password:}" />

        <property name="databaseSchemaUpdate" value="true" />
      </bean>

    </beans>

With this configuration the properties would be first looked up in the /opt/conf/flowable.properties file.

## Supported databases

Listed below are the types (case sensitive!) that Flowable uses to refer to databases.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Flowable database type</th>
<th>Example JDBC URL</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>h2</p></td>
<td><p>jdbc:h2:tcp://localhost/flowable</p></td>
<td><p>Default configured database</p></td>
</tr>
<tr class="even">
<td><p>mysql</p></td>
<td><p>jdbc:mysql://localhost:3306/flowable?autoReconnect=true</p></td>
<td><p>Tested using mysql-connector-java database driver</p></td>
</tr>
<tr class="odd">
<td><p>oracle</p></td>
<td><p>jdbc:oracle:thin:@localhost:1521:xe</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>postgres</p></td>
<td><p>jdbc:postgresql://localhost:5432/flowable</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>db2</p></td>
<td><p>jdbc:db2://localhost:50000/flowable</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>mssql</p></td>
<td><p>jdbc:sqlserver://localhost:1433;databaseName=flowable (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) <em>OR</em> jdbc:jtds:sqlserver://localhost:1433/flowable (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)</p></td>
<td><p>Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver</p></td>
</tr>
</tbody>
</table>

## Creating the database tables

The easiest way to create the database tables for your database is to:

-   Add the flowable-cmmn-engine JARs to your classpath

-   Add a suitable database driver

-   Add a Flowable configuration file (*flowable.cmmn.cfg.xml*) to your classpath, pointing to your database (see [database configuration section](cmmn/ch02-Configuration.md#database-configuration))

-   Execute the main method of the *DbSchemaCreate* class

However, often only database administrators can execute DDL statements on a database. On a production system, this is also the wisest of choices. The SQL DDL statements can be found on the Flowable downloads page or inside the Flowable distribution folder, in the database subdirectory. The scripts are also in the engine JAR (*flowable-cmmn-engine-x.jar*), in the package *org/flowable/cmmn/db/create*. The SQL files are of the form

    flowable.{db}.cmmn.create.sql

Where *db* is any of the [supported databases](cmmn/ch02-Configuration.md#supported-databases).

## Database table names explained

The database names of the Flowable CMMN Engine all start with **ACT\_CMMN\_**. The second part is a two-character identification of the use case of the table. This use case will also roughly match the service API.

-   **ACT\_CMMN\_**\*: Tables without an additional prefix contain 'static' information such as case definitions and case resources (images, rules, etc.).

-   **ACT\_CMMN\_RU\_**\*: 'RU' stands for runtime. These are the runtime tables that contain the runtime data of case instances, plan items, and so on. Flowable only stores the runtime data during case instance execution and removes the records when a case instance ends. This keeps the runtime tables small and fast.

-   **ACT\_CMMN\_HI\_**\*: 'HI' stands for history. These are the tables that contain historical data, such as past case instances, plan items, and so on.

## Database upgrade

Make sure you make a backup of your database (using your database backup capabilities) before you run an upgrade.

By default, a version check will be performed each time a process engine is created. This typically happens once at boot time of your application or of the Flowable webapps. If the Flowable library notices a difference between the library version and the version of the Flowable database tables, then an exception is thrown.

To upgrade, you have to start by putting the following configuration property in your flowable.cmmn.cfg.xml configuration file:

    <beans >

      <bean id="cmmnEngineConfiguration"
          class="org.flowable.cmmn.engine.CmmnEngineConfiguration">
        
        <property name="databaseSchemaUpdate" value="true" />
        
      </bean>

    </beans>

**Also, include a suitable database driver for your database to the classpath.** Upgrade the Flowable libraries in your application. Or start up a new version of Flowable and point it to a database that contains data from an older version. With databaseSchemaUpdate set to true, Flowable will automatically upgrade the DB schema to the newest version the first time when it notices that libraries and DB schema are out of sync.

**As an alternative, you can also run the upgrade DDL statements.** It’s also possible to run the upgrade database scripts available on the Flowable downloads page.

## History configuration

Customizing the configuration of history storage is optional. This allows you to tweak settings that influence the [history capabilities](#history) of the engine. See [history configuration](#historyConfig) for more details.

    <property name="history" value="audit" />

## Exposing configuration beans in expressions and scripts

By default, all beans that you specify in the flowable.cmmn.cfg.xml configuration or in your own Spring configuration file are available to expressions and scripts. If you want to limit the visibility of beans in your configuration file, you can configure a property called beans in your process engine configuration. The beans property in CmmnEngineConfiguration is a map. When you specify that property, only beans specified in that map will be visible to expressions and scripts. The exposed beans will be exposed with the names as you specify in the map.

## Deployment cache configuration

All case definitions are cached (after they’re parsed) to avoid hitting the database every time a case definition is needed and because case definition data doesn’t change. By default, there is no limit on this cache. To limit the case definition cache, add the following property:

    <property name="caseDefinitionCacheLimit" value="10" />

Setting this property will swap the default hashmap cache with a LRU cache that has the provided hard limit. Of course, the 'best' value for this property depends on the total amount of case definitions stored and the number of case definitions actually used at runtime by all the runtime case instances.

You can also inject your own cache implementation. This must be a bean that implements the org.flowable.engine.common.impl.persistence.deploy.DeploymentCache interface:

    <property name="caseDefinitionCache">
      <bean class="org.flowable.MyCache" />
    </property>

## Logging

All logging (flowable, spring, mybatis, …​) is routed through SLF4J and allows for selecting the logging-implementation of your choice.

**By default no SFL4J-binding JAR is present in the flowable-cmmn-engine dependencies, this should be added in your project in order to use the logging framework of your choice.** If no implementation JAR is added, SLF4J will use a NOP-logger, not logging anything at all, other than a warning that nothing will be logged. For more info on these bindings [<http://www.slf4j.org/codes.html#StaticLoggerBinder>](http://www.slf4j.org/codes.html#StaticLoggerBinder).

With Maven, add for example a dependency like this (here using log4j), note that you still need to add a version:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-reload4j</artifactId>
    </dependency>

The flowable-rest webapp is configured to use Log4j-binding. Log4j is also used when running the tests for all the flowable-\* modules.

**Important note when using a container with commons-logging in the classpath:** In order to route the spring-logging through SLF4J, a bridge is used (see [<http://www.slf4j.org/legacy.html#jclOverSLF4J>](http://www.slf4j.org/legacy.html#jclOverSLF4J)). If your container provides a commons-logging implementation, please follow directions on this page: [<http://www.slf4j.org/codes.html#release>](http://www.slf4j.org/codes.html#release) to ensure stability.

Example when using Maven (version omitted):

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
    </dependency>

---

### Docusaurus Docs Cmmn Ch03 API (`docs/docusaurus/docs/cmmn/ch03-API.md`)

---
id: ch03-API
title: The Flowable CMMN API
---

## The Process CMMN Engine API and services

The engine API is the most common way of interacting with Flowable. The main starting point is the CmmnEngine, which can be created in several ways as described in the [configuration section](cmmn/ch02-Configuration.md#creating-a-cmmnengine). From the CmmnEngine, you can obtain the various services that contain the case/CMMN methods. CmmnEngine and the services objects are thread safe, so you can keep a reference to one of those for a whole server.

    CmmnEngine cmmnEngine = CmmnEngineConfiguration.createStandaloneCmmnEngineConfiguration();

    CmmnRuntimeService runtimeService = cmmnEngine.getCmmnRuntimeService();
    CmmnRepositoryService repositoryService = cmmnEngine.getCmmnRepositoryService();
    CmmnTaskService taskService = cmmnEngine.getCmmnTaskService();
    CmmnManagementService managementService = cmmnEngine.getCmmnManagementService();
    CmmnHistoryService historyService = cmmnEngine.getCmmnHistoryService();

CmmnEngineConfiguration.createStandaloneCmmnEngineConfiguration() will initialize and build a CMMN engine and afterwards always return the CMMN engine.

The CmmnEngineConfiguration class will scan for all flowable.cmmn.cfg.xml and flowable-cmmn-context.xml files. For all flowable.cmmn.cfg.xml files, the CMMN engine will be built in the typical Flowable way: CmmnEngineConfiguration.createCmmnEngineConfigurationFromInputStream(inputStream).buildCmmnEngine(). For all flowable-cmmn-context.xml files, the CMMN engine will be built in the Spring way: first the Spring application context is created and then the CMMN engine is obtained from that application context.

All services are stateless. This means that you can easily run Flowable on multiple nodes in a cluster, each going to the same database, without having to worry about which machine actually executed previous calls. Any call to any service is idempotent regardless of where it is executed.

The **CmmnRepositoryService** is probably the first service needed when working with the Flowable CMMN engine. This service offers operations for managing and manipulating deployments and case definitions. Without going into much detail here, a case definition is a Java counterpart of the CMMN 1.1 case. It is a representation of the structure and behavior of each of the steps of a case. A deployment is the unit of packaging within the Flowable CMMN engine. A deployment can contain multiple CMMN 1.1 XML files and any other resource. The choice of what is included in one deployment is up to the developer. It can range from a single process CMMN 1.1 XML file to a whole package of cases and relevant resources (for example, the deployment 'hr-cases' could contain everything related to HR cases). The CmmnRepositoryService can deploy such packages. Deploying a deployment means it is uploaded to the engine, where all cases are inspected and parsed before being stored in the database. From that point on, the deployment is known to the system and any process included in the deployment can now be started.

Furthermore, this service allows you to:

-   Query on deployments and case definitions known to the engine.

-   Retrieve various resources, such as files contained within the deployment or case diagrams that were auto-generated by the engine.

-   Retrieve a POJO version of the case definition, which can be used to introspect the case using Java rather than XML.

While the CmmnRepositoryService is mostly about static information (data that doesn’t change, or at least not a lot), the **CmmnRuntimeService** is quite the opposite. It deals with starting new case instances of case definitions. As said above, a case definition defines the structure and behavior of the different steps in a case. A case instance is one execution of such a case definition. For each case definition there typically are many instances running at the same time. The CmmnRuntimeService also is the service that is used to retrieve and store case variables. This is data that is specific to the given case instance and can be used by various constructs in the case (for example, a plan transition condition often uses process variables to determine which path is chosen to continue the case). The CmmnRuntimeservice also allows you to query on case instances and plan items. Plan items are a representation of the enabled plan items of CMMN 1.1. Lastly, the CmmnRuntimeService is used whenever a case instance is waiting for an external trigger and the case needs to be continued. A case instance can have various wait states and this service contains various operations to 'signal' to the instance that the external trigger is received and the case instance can be continued.

Tasks that need to be performed by human users of the system are core to a CMMN engine such as Flowable. Everything around tasks is grouped in the **CmmnTaskService**, such as:

-   Querying tasks assigned to users or groups

-   Creating new *standalone* tasks. These are tasks that are not related to a process instance.

-   Manipulating to which user a task is assigned or which users are in some way involved with the task.

-   Claiming and completing a task. Claiming means that someone decided to be the assignee for the task, meaning that this user will complete the task. Completing means 'doing the work of the tasks'. Typically this is filling in a form of sorts.

The **CmmnHistoryService** exposes all historical data gathered by the Flowable CMMN engine. When executing cases, a lot of data can be kept by the engine (this is configurable), such as case instance start times, who did which tasks, how long it took to complete the tasks, which path was followed in each case instance, and so on. This service exposes mainly query capabilities to access this data.

The **CmmnManagementService** gives access to low-level information about the database tables, allows to query for the different types of jobs and to execute them.

For more detailed information on the service operations and the engine API, see [the javadocs](http://www.flowable.org/docs/javadocs/index.html).

## Exception strategy

The base exception in Flowable is the org.flowable.engine.common.api.FlowableException, an unchecked exception. This exception can be thrown at all times by the API, but 'expected' exceptions that happen in specific methods are documented in [the javadocs](http://www.flowable.org/docs/javadocs/index.html). For example, an extract from CmmnTaskService:

    /**
     * Called when the task is successfully executed.
     * @param taskId the id of the task to complete, cannot be null.
     * @throws FlowableObjectNotFoundException when no task exists with the given id.
     */
     void complete(String taskId);

In the example above, when an id is passed for which no task exists, an exception will be thrown. Also, since the javadoc **explicitly states that taskId cannot be null, an FlowableIllegalArgumentException will be thrown when null is passed**.

Even though we want to avoid a big exception hierarchy, the following subclasses are thrown in specific cases. All other errors that occur during process-execution or API-invocation that don’t fit into the possible exceptions below are thrown as regular FlowableExceptions.

-   FlowableWrongDbException: Thrown when the Flowable engine discovers a mismatch between the database schema version and the engine version.

-   FlowableOptimisticLockingException: Thrown when an optimistic locking occurs in the data store caused by concurrent access of the same data entry.

-   FlowableClassLoadingException: Thrown when a class requested to load was not found or when an error occurred while loading it (e.g., JavaDelegates, TaskListeners, …​).

-   FlowableObjectNotFoundException: Thrown when an object that is requested or actioned does not exist.

-   FlowableIllegalArgumentException: An exception indicating that an illegal argument has been supplied in a Flowable API-call, an illegal value was configured in the engine’s configuration or an illegal value has been supplied or an illegal value is used in a process definition.

-   FlowableTaskAlreadyClaimedException: Thrown when a task is already claimed, when the taskService.claim(...) is called.

## Query API

There are two ways of querying data from the engine: the query API and native queries. The Query API allows you to program completely typesafe queries with a fluent API. You can add various conditions to your queries (all of which are applied together as a logical AND) and precisely one ordering. The following code shows an example:

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

## Variables

Every case instance needs and uses data to execute the steps it’s made up of. In Flowable, this data is called *variables*, which are stored in the database. Variables can be used in expressions (for example, in the condition of a sentry), in Java service tasks when calling external services (for example to provide the input or store the result of the service call), and so on.

A case instance can have variables (called *case variables*), but also *plan item instances* and human tasks can have variables. A case instance can have any number of variables. Each variable is stored in a row in the *ACT\_RU\_VARIABLE* database table.

The *createCaseInstanceBuilder* method has optional methods to provide the variables when the case instance is created and started through the *CmmnRuntimeService*:

    CaseInstance caseInstance = runtimeService.createCaseInstanceBuilder().variable("var1", "test").start();

Variables can be added during case execution. For example, (*CmmnRuntimeService*):

    void setVariables(String caseInstanceId, Map<String, ? extends Object> variables);

Variables can also be retrieved, as shown below. Note that similar methods exist on the *CmmnTaskService*.

    Map<String, Object> getVariables(String caseInstanceId);
    Object getVariable(String caseInstanceId, String variableName);

Variables are often used in Java service tasks, expressions, scripts, and so on.

## Transient variables

Transient variables are variables that behave like regular variables but are not persisted. Typically, transient variables are used for advanced use cases. When in doubt, use a regular case variable.

The following applies for transient variables:

-   There is no history stored at all for transient variables.

-   Like *regular* variables, transient variables are put on the *highest parent* when set. This means that when setting a variable on a plan item, the transient variable is actually stored on the case instance execution. Like regular variables, a *local* variant of the method exists if the variable is set on the specific plan item or task.

-   A transient variable can only be accessed before the next 'wait state' in the case definition. After that, they are gone. Here, the wait state means the point in the case instance where it is persisted to the data store.

-   Transient variables can only be set by the *setTransientVariable(name, value)*, but transient variables are also returned when calling *getVariable(name)* (a *getTransientVariable(name)* also exists, that only checks the transient variables). The reason for this is to make the writing of expressions easy and existing logic using variables works for both types.

-   A transient variable *shadows* a persistent variable with the same name. This means that when both a persistent and transient variable is set on a case instance and *getVariable("someVariable")* is called, the transient variable value will be returned.

You can set and get transient variables in most places where regular variables are exposed:

-   On *DelegatePlanItemInstance* in *PlanItemJavaDelegate* implementations

-   When starting a case instance through the runtime service

-   When completing a task

The methods follow the naming convention of the regular case variables:

    CaseInstance caseInstance = runtimeService.createCaseInstanceBuilder().transientVariable("var1", "test").start();

## Expressions

Flowable uses UEL for expression-resolving. UEL stands for *Unified Expression Language* and is part of the EE6 specification (see [the EE6 specification](http://docs.oracle.com/javaee/6/tutorial/doc/gjddd.html) for detailed information).

Expressions can be used in, for example, Java Service tasks, sentry conditions and plan item listeners. Although there are two types of expressions, value-expression and method-expression, Flowable abstracts this so they can both be used where an expression is expected.

-   **Value expression**: resolves to a value. By default, all case variables are available to use. Also, all spring-beans (if using Spring) are available to use in expressions. In non-Spring environments the beans available to expressions can be set through the setBeans method of the CmmnEngineConfiguration. Some examples:



    ${myVariable}
    ${myBean.myProperty}

-   **Method expression**: invokes a method with or without parameters. **When invoking a method without parameters, be sure to add empty parentheses after the method-name (as this distinguishes the expression from a value expression).** The passed parameters can be literal values or expressions that are resolved themselves. Examples:



    ${printer.print()}
    ${myBean.addNewOrder('orderName')}
    ${myBean.doSomething(myVar, planItemInstance)}

These expressions support resolving primitives (including comparing them), beans, lists, arrays, and maps.

On top of all case instance variables, there are default objects available that can be used in expressions:

-   caseInstance: Holds additional information about the ongoing case instance. The caseInstance keyword is available in all expressions.

-   planItemInstance: The DelegatePlanItemInstance holds additional information about the current plan item instance. The planItemInstance keyword is available in all plan item related expressions (e.g. sentry conditions, plan item lifecycle listeners, service task expression, etc.).

-   planItemInstances: Exposes information about all current plan item instance. See the examples below on how to use it.

-   variableContainer: The VariableContainer for which the expression is being resolved for. A variable container is an abstraction on top of case instances, plan item instances, process instances and executions. The +variableContainer keyword allows to write expressions that are not bound to a specific implementation.

-   authenticatedUserId: The id of the user that is currently authenticated. If no user is authenticated, the variable is not available.

For example:

    ${caseInstance.id}
    ${caseInstance.getVariable('myVariable') == 'test'}
    ${caseInstance.setVariable('myVariable', 'test')}

    ${planItemInstance.getPlanItem().getPlanItemDefinition().getName()}
    ${planItemInstance.getVariable('myVariable') == 123}
    ${planItemInstance.setVariable('myVariable', 123)}

    ${variableContainer.getVariable('myVariable')}
    ${variableContainer.setVariable('myVariable', 'true')}

The keyword **planItemInstances** deserves some more explanation. Using this keyword it is possible to retrieve all the current plan item instances, but it also acts like a sort of API to retrieve more information about the current plan item instance.

For example, the following expression

    ${planItemInstances.active().count()}

Will return a count of all plan item instances that are currently in the 'active' state. If we’re only interested in a certain plan item, it can be filtered down:

    ${planItemInstances.definitionId('a').active().count()}

As the example shows, the planItemInstances keyword allows to chain together various filter methods. Such chaining will use AND semantics. The following methods are supported.

Methods that filter on plan item instance state:

-   active()

-   available()

-   enabled()

-   disabled()

-   completed()

-   terminated()

The following state filters are also supported, but do note these reflect non-spec compliant internal states:

-   unavailable()

-   waitingForRepetition()

-   asyncActive()

To get all plan item instances that are in a terminal (i.e. terminated or completed) or non-terminal state:

-   onlyTerminal()

-   onlyNonTerminal()

To filter based on the identifier that is set in the CMMN model:

-   definitionId('id1')

-   definitionIds('id1', 'id2')

To filter based on the name:

-   name('name1')

-   names('name1', 'name2', 'name3')

To filter using a lambda expression:

-   filter(planItemInstance -> planItemInstance.name.startsWith('Service')

For some use cases, the plan item instances that should be filtered should only be part of the current stage. The 'current stage' is either the parent stage of a plan item or the case instance when there’s no parent stage.

-   currentStage()

Lastly, there is a set of methods that cannot be chained, as they return a result.

-   count(): returns a count of plan item instances, after applying all filters.

-   getDefinitionIds(): returns a list of strings with all the ids as defined in the CMMN model of the matching plan item instances.

-   getDefinitionNames(): returns a list of names with all the names as defined in the CMMN model of the matching plan item instances.

-   getList(): returns the 'raw' list of *org.flowable.cmmn.api.runtime.PlanItemInstance* instances.

Let’s look at some examples where the above methods are used in expressions:

To count all active plan item instances in a case instance:

    ${planItemInstances.active().count()}

To do a count of all active plan item instances with an id 'a' or 'b':

    ${planItemInstances.active().definitionIds('a', 'b').count()}

To get all the ids of the plan item instances which are in a terminal state in the current stage:

    ${planItemInstances.currentStage().onlyTerminal().getDefinitionIds()()}

To store the result of the above expression in a transient variable

    ${caseInstance.setTransientVariable('myVar', planItemInstances.currentStage().onlyTerminal().getDefinitionIds()}}

## Expression functions

\[Experimental\] Expression functions have been added in version 6.4.0.

To make working with case variables easier, a set of out-of-the-box functions is available, under the *variables* namespace.

-   **variables:get(varName)**: Retrieves the value of a variable. The main difference with writing the variable name directly in the expression is that using this function won’t throw an exception when the variable doesn’t exist. For example *${myVariable == "hello"}* would throw an exception if *myVariable* doesn’t exist, but *${var:get(myVariable) == 'hello'}* will just work.

-   **variables:getOrDefault(varName, defaultValue)**: similar to *get*, but with the option of providing a default value which is returned when the variable isn’t set or the value is *null*.

-   **variables:exists(varName)**: Returns *true* if the variable has a non-null value.

-   **variables:isEmpty(varName)** (alias *:empty*) : Checks if the variable value is not empty. Depending on the variable type, the behavior is the following:

    -   For String variables, the variable is deemed empty if it’s the empty string.

    -   For java.util.Collection variables, *true* is returned if the collection has no elements.

    -   For ArrayNode variables, *true* is returned if there are no elements.

    -   In case the variable is *null*, *true* is always returned.

-   **variables:isNotEmpty(varName)** (alias *:notEmpty*) : the reverse operation of *isEmpty*.

-   **variables:equals(varName, value)** (alias *:eq*) : checks if a variable is equal to a given value. This is a shorthand function for an expression that would otherwise be written as *${execution.getVariable("varName") != null && execution.getVariable("varName") == value}*.

    -   If the variable value is null, false is returned (unless compared to null).

-   **variables:notEquals(varName, value)** (alias *:ne*) : the reverse comparison of *equals*.

-   **variables:contains(varName, value1, value2, …​)**: checks if **all** values provided are contained within a variable. Depending on the variable type, the behavior is the following:

    -   For String variables, the passed values are used as substrings that need to be part of the variable.

    -   For java.util.Collection variables, all the passed values need to be an element of the collection (regular *contains* semantics).

    -   For ArrayNode variables: supports checking if the arraynode contains a JsonNode for the types that are supported as variable type.

    -   When the variable value is null, false is returned in all cases. When the variable value is not null, and the instance type is not one of the types above, false will be returned.

-   **variables:containsAny(varName, value1, value2, …​)** : similar to the *contains* function, but *true* will be returned if **any** (and not all) the passed values is contained in the variable.

-   **variables:base64(varName)** : converts a Binary or String variable to a Base64 String

-   Comparator functions:

    -   **variables:lowerThan(varName, value)** (alias *:lessThan* or *:lt*) : shorthand for *${execution.getVariable("varName") != null && execution.getVariable("varName") &lt; value}*.

    -   **variables:lowerThanOrEquals(varName, value)** (alias *:lessThanOrEquals* or *:lte*) : similar, but now for *&lt; =*.

    -   **variables:greaterThan(varName, value)** (alias *:gt*) : similar, but now for *&gt;*.

    -   **variables:greaterThanOrEquals(varName, value)** (alias *:gte*) : similar, but now for *&gt; =*.

The *variables* namespace is aliased to *vars* or *var*. So *variables:get(varName)* is equivalent to writing *vars:get(varName)* or *var:get(varName)*. Note that it’s not needed to put quotes around the variable name: *var:get(varName)* is equivalent to *var:get(\\'varName')* or *var:get("varName")*.

Also note that in none of the functions above the *planItemInstance* or *caseInstance* needs to be passed into the function (as would be needed when not using a function). The engine will inject the appropriate variable scope when invoking the function. This also means that these functions can be used in exactly the same way when writing expressions in BPMN process definitions.

The use of these variable functions is especially useful in CMMN, for example when it comes to writing the condition of an if-part of sentry. Take the following CMMN case definition:



Assume the sentry has an if-part besides the completion event. Right after a case instance is started, this if-part condition will be evaluated (as the stage becomes available). If the condition is of the form *${someVariable == someValue}*, this means the variable needs to be available when starting the case instance. In many cases, this is not possible or the variable comes later (e.g., from a form), which leads to a low-level *PropertyNotFoundException*. Taking the potential nullability into account, the correct expression would have to be:

    ${planItemInstance.getVariable('someVariable') != null && planItemInstance.getVariable('someVariable') == someValue}

Which is quite long. Using the functions above however, this can be simplified to

    ${var:eq(someVariable, someValue)}

or

    ${var:get(someVariable) == someValue}

The function implementations take into account the nullability of the variable (and not throw an exception in case the variable is null) and will handle the equality correctly.

Additionally, it’s possible to register custom functions that can be used in expressions. See the org.flowable.common.engine.api.delegate.FlowableFunctionDelegate interface for more information.

## History Cleaning

By default history data is stored forever, this can cause the history tables to grow very large and impact the performance of the HistoryService.  History Cleaning has been introduced with 6.5.0 and allows the deletion of HistoricProcessInstances and their associated data.  Once process data no longer needs to be retained it can be deleted to reduce the history database's size. 

### Automatic History Cleaning Configuration

Automatic cleanup of HistoricCaseInstances is disabled by default but can be enabled and configured programmatically.  Once enabled the default is to run a cleanup job at 1 AM to delete all HistoricCaseInstances and associated data that have ended 365 days prior or older.
The deletion of the historical processes is done using the Flowable Batch mechanism, by scheduling jobs that are going to delete the processes in batches and store the information about what was done in a batch table.

    CmmnEngine cmmnEngine = CmmnEngineConfiguration.
        .createProcessEngineConfigurationFromResourceDefault()
        .setEnableHistoryCleaning(true)
        .setHistoryCleaningTimeCycleConfig("0 0 1 * * ?")
        .setCleanInstancesEndedAfter(Duration.ofDays(365))
        .buildCmmnEngine();
 
Spring properties set in an application.properties or externalized configuration are also available:
 
     flowable.enable-history-cleaning=true
     flowable.history-cleaning-after=365d
     flowable.history-cleaning-cycle=0 0 1 * * ?
 
### Manually Deleting History

[//]: # (TODO change examples)

Manually cleaning history can be accomplished by executing methods on the CmmnHistoryService query builders.

Delete all HistoricCaseInstances and their related data that are older than one year.

     int numberOfCasesInBatch = 10;
     Calendar cal = new GregorianCalendar();
     cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
     cmmnHistoryService.createHistoricCaseInstanceQuery()
       .finishedBefore(cal.getTime())
       .deleteSequentiallyUsingBatch(numberOfCasesInBatch, "Custom Delete Batch");

## Unit testing

Cases are an integral part of software projects and they should be tested in the same way normal application logic is tested: with unit tests.
Since Flowable is an embeddable Java engine, writing unit tests for business cases is as simple as writing regular unit tests.

Flowable supports JUnit Jupiter styles of unit testing.

In the JUnit Jupiter style one needs to use the org.flowable.cmmn.engine.test.FlowableCmmnTest annotation or register the org.flowable.cmmn.engine.test.FlowableCmmnExtension manually.
The FlowableCmmnTest annotation is just a meta-annotation and does the registration of the FlowableCmmnExtension (i.e. it does @ExtendWith(FlowableCmmnExtension.class)).
This will make the CmmnEngine and the services available as parameters into the test and lifecycle methods (@BeforeAll, @BeforeEach, @AfterEach, @AfterAll).
Before each test the cmmnEngine will be initialized by default with the flowable.cmmn.cfg.xml resource on the classpath.
In order to specify a different configuration file the org.flowable.cmmn.engine.test.CmmnConfigurationResource annotation needs to be used (see the second example).
Cmmn engines are cached statically over multiple unit tests when the configuration resource is the same.

By using FlowableCmmnExtension, you can annotate test methods with org.flowable.cmmn.engine.test.CmmnDeployment.
When a test method is annotated with @CmmnDeployment, before each test the cmmn files defined in CmmnDeployment\#resources will be deployed.
In case there are no resources defined, a resource file of the form testClassName.testMethod.cmmn in the same package as the test class, will be deployed.
At the end of the test, the deployment will be deleted, including all related case instances, tasks, and so on.
See the CmmnDeployment class for more information.

Taking all that into account, a JUnit Jupiter test looks as follows:

**Junit Jupiter test with the default resource.**

    @FlowableCmmnTest
    class MyTest {

      private CmmnEngine cmmnEngine;
      private CmmnRuntimeService cmmnRuntimeService;
      private CmmnTaskService cmmnTaskService;

      @BeforeEach
      void setUp(CmmnEngine cmmnEngine) {
        this.cmmnEngine = cmmnEngine;
        this.cmmnRuntimeService = cmmnEngine.getCmmnRuntimeService();
        this.cmmnTaskService = cmmnEngine.getTaskRuntimeService();
      }

      @Test
      @CmmnDeployment
      void testSingleHumanTask() {
        CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
                        .caseDefinitionKey("myCase")
                        .start();
        assertNotNull(caseInstance);

        Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
        assertEquals("Task 1", task.getName());
        assertEquals("JohnDoe", task.getAssignee());

        cmmnTaskService.complete(task.getId());
        assertEquals(0, cmmnRuntimeService.createCaseInstanceQuery().count());
      }
    }

With JUnit Jupiter you can also inject the id of the deployment (with +org.flowable.cmmn.engine.test.CmmnDeploymentId+_) into your test and lifecycle methods.

**Junit Jupiter test with custom resource.**

    @FlowableCmmnTest
    @CmmnConfigurationResource("flowable.custom.cmmn.cfg.xml")
    class MyTest {

      private CmmnEngine cmmnEngine;
      private CmmnRuntimeService cmmnRuntimeService;
      private CmmnTaskService cmmnTaskService;

      @BeforeEach
      void setUp(CmmnEngine cmmnEngine) {
        this.cmmnEngine = cmmnEngine;
        this.cmmnRuntimeService = cmmnEngine.getCmmnRuntimeService();
        this.cmmnTaskService = cmmnEngine.getTaskRuntimeService();
      }
      @Test
      @CmmnDeployment
      void testSingleHumanTask() {
        CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
                        .caseDefinitionKey("myCase")
                        .start();
        assertNotNull(caseInstance);

        Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
        assertEquals("Task 1", task.getName());
        assertEquals("JohnDoe", task.getAssignee());

        cmmnTaskService.complete(task.getId());
        assertEquals(0, cmmnRuntimeService.createCaseInstanceQuery().count());
      }
    }

---

### Docusaurus Docs Cmmn Ch04 Spring (`docs/docusaurus/docs/cmmn/ch04-Spring.md`)

---
id: ch04-Spring
title: Spring integration
---

While you can definitely use Flowable without Spring, we’ve provided some very nice integration features that are explained in this chapter.

## CmmnEngineFactoryBean

The CmmnEngine can be configured as a regular Spring bean. The starting point of the integration is the class org.flowable.cmmn.spring.CmmnEngineFactoryBean. That bean takes a CMMN engine configuration and creates the CMMN engine. This means that the creation and configuration of properties for Spring is the same as documented in the [configuration section](cmmn/ch02-Configuration.md#creating-a-cmmnengine). For Spring integration, the configuration and engine beans will look like this:

    <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.spring.SpringCmmnEngineConfiguration">
        ...
    </bean>

    <bean id="cmmnEngine" class="org.flowable.cmmn.spring.CmmnEngineFactoryBean">
      <property name="cmmnEngineConfiguration" ref="cmmnEngineConfiguration" />
    </bean>

Note that the cmmnEngineConfiguration bean now uses the org.flowable.cmmn.spring.SpringCmmnEngineConfiguration class.

## Default Spring configuration

The section shown below contains the dataSource, transactionManager, cmmnEngine and the Flowable engine services.

When passing the DataSource to the SpringCmmnEngineConfiguration (using property "dataSource"), Flowable uses a org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy internally, which wraps the passed DataSource. This is done to make sure the SQL connections retrieved from the DataSource and the Spring transactions play well together. This implies that it’s no longer necessary to proxy the dataSource yourself in Spring configuration, although it’s still possible to pass a TransactionAwareDataSourceProxy into the SpringCmmnEngineConfiguration. In this case, no additional wrapping will occur.

**Make sure when declaring a TransactionAwareDataSourceProxy in Spring configuration yourself that you don’t use it for resources that are already aware of Spring transactions (e.g. DataSourceTransactionManager need the un-proxied dataSource).**

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                                 http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context
                                 http://www.springframework.org/schema/context/spring-context-2.5.xsd
                               http://www.springframework.org/schema/tx
                                 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

      <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="username" value="sa" />
        <property name="password" value="" />
      </bean>

      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
      </bean>

      <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.spring.SpringCmmnEngineConfiguration">
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="databaseSchemaUpdate" value="true" />
      </bean>

      <bean id="cmmnEngine" class="org.flowable.cmmn.spring.CmmnEngineFactoryBean">
        <property name="cmmnEngineConfiguration" ref="cmmnEngineConfiguration" />
      </bean>

      <bean id="cmmnRepositoryService" factory-bean="cmmnEngine" factory-method="getCmmnRepositoryService" />
      <bean id="cmmnRuntimeService" factory-bean="cmmnEngine" factory-method="getCmmnRuntimeService" />
      <bean id="cmmnTaskService" factory-bean="cmmnEngine" factory-method="getCmmnTaskService" />
      <bean id="cmmnHistoryService" factory-bean="cmmnEngine" factory-method="getCmmnHistoryService" />
      <bean id="cmmnManagementService" factory-bean="cmmnEngine" factory-method="getCmmnManagementService" />

    ...

First, the application context is created using any of the ways supported by Spring. In this example, you could use a classpath XML resource to configure our Spring application context:

    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
        "org/flowable/cmmn/examples/spring/SpringIntegrationTest-context.xml");

or, as it’s a test:

    @ContextConfiguration(
      "classpath:org/flowable/cmmn/spring/test/SpringIntegrationTest-context.xml")

## Expressions

When using the CmmnEngineFactoryBean, all expressions in the CMMN processes will also 'see' all the Spring beans, by default. It’s possible to limit the beans (even none) you want to expose in expressions using a map that you can configure. The example below exposes a single bean (printer), available to use under the key "printer". **To have NO beans exposed at all, just pass an empty list as 'beans' property on the SpringCmmnEngineConfiguration. When no 'beans' property is set, all Spring beans in the context will be available.**

    <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.spring.SpringCmmnEngineConfiguration">
      ...
      <property name="beans">
        <map>
          <entry key="printer" value-ref="printer" />
        </map>
      </property>
    </bean>

    <bean id="printer" class="org.flowable.cmmn.examples.spring.Printer" />

Now the exposed beans can be used in expressions:

    ...
        <case id="myCase">
            <casePlanModel id="myPlanModel" name="My CasePlanModel">

                <planItem id="planItem1" name="Task One" definitionRef="serviceTask" />
                <planItem id="planItem2" name="The Case" definitionRef="task">
                    <entryCriterion sentryRef="sentry1" />
                </planItem>

                <sentry id="sentry1">
                    <planItemOnPart sourceRef="planItem1">
                        <standardEvent>complete</standardEvent>
                    </planItemOnPart>
                </sentry>

                <task id="serviceTask" flowable:type="java" flowable:expression="${printer.printMessage(var1)}" flowable:resultVariableName="customResponse" />
                <task id="task" name="The Task" isBlocking="true" />

            </casePlanModel>
        </case>

Where Printer looks like this:

    public class Printer {

      public void printMessage(String var) {
        System.out.println("hello " + var);
      }
    }

And the Spring bean configuration (also shown above) looks like this:

    <beans>
      ...

      <bean id="printer" class="org.flowable.cmmn.examples.spring.Printer" />

    </beans>

## Automatic resource deployment

Spring integration also has a special feature for deploying resources. In the CMMN engine configuration, you can specify a set of resources. When the CMMN engine is created, all those resources will be scanned and deployed. There is filtering in place that prevents duplicate deployments. Only when the resources have actually changed will new deployments be deployed to the Flowable DB. This makes sense in a lot of use cases, where the Spring container is rebooted frequently (for example, testing).

Here’s an example:

    <bean id="cmmnEngineConfiguration" class="org.flowable.cmmn.spring.SpringCmmnEngineConfiguration">
      ...
      <property name="deploymentResources"
        value="classpath*:/org/flowable/cmmn/spring/test/autodeployment/autodeploy.*.cmmn" />
    </bean>

    <bean id="cmmnEngine" class="org.flowable.cmmn.spring.CmmnEngineFactoryBean">
      <property name="cmmnEngineConfiguration" ref="cmmnEngineConfiguration" />
    </bean>

By default, the configuration above will group all of the resources matching the filter into a single deployment to the Flowable engine. The duplicate filtering to prevent re-deployment of unchanged resources applies to the whole deployment. In some cases, this may not be what you want. For instance, if you deploy a set of process resources this way and only a single case definition in those resources has changed, the deployment as a whole will be considered new and all of the case definitions in that deployment will be re-deployed, resulting in new versions of each of the case definitions, even though only one was actually changed.

To be able to customize the way deployments are determined, you can specify an additional property in the SpringCmmnEngineConfiguration, deploymentMode. This property defines the way deployments will be determined from the set of resources that match the filter. There are 3 values that are supported by default for this property:

-   default: Group all resources into a single deployment and apply duplicate filtering to that deployment. This is the default value and it will be used if you don’t specify a value.

-   single-resource: Create a separate deployment for each individual resource and apply duplicate filtering to that deployment. This is the value you would use to have each process definition be deployed separately and only create a new case definition version if it has changed.

-   resource-parent-folder: Create a separate deployment for resources that share the same parent folder and apply duplicate filtering to that deployment. This value can be used to create separate deployments for most resources, but still be able to group some by placing them in a shared folder. Here’s an example of how to specify the single-resource configuration for deploymentMode:



    <bean id="cmmnEngineConfiguration"
        class="org.flowable.cmmn.spring.SpringCmmnEngineConfiguration">
      ...
      <property name="deploymentResources" value="classpath*:/flowable/*.cmmn" />
      <property name="deploymentMode" value="single-resource" />
    </bean>

In addition to using the values listed above for deploymentMode, you may require customized behavior towards determining deployments. If so, you can create a subclass of SpringCmmnEngineConfiguration and override the getAutoDeploymentStrategy(String deploymentMode) method. This method determines which deployment strategy is used for a certain value of the deploymentMode configuration.

## Unit testing

When integrating with Spring, business cases can be tested very easily using the standard standard [Flowable testing facilities](cmmn/ch03-API.md#unit-testing).
The following examples show how a case definition is tested in typical Spring-based JUnit Jupiter test:

**JUnit Jupiter test.**

    @ExtendWith(FlowableCmmnSpringExtension.class)
    @SpringJUnitConfig(CmmnSpringJunitJupiterTest.TestConfiguration.class)
    class MyBusinessCaseTest {

      @Autowired
      private CmmnRepositoryService cmmnRepositoryService;

      @Autowired
      private CmmnRuntimeService cmmnRuntimeService;

      @Test
      @CmmnDeployment
      public void simpleCaseTest() {
        CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
                .caseDefinitionKey("simpleCase")
                .variable("var1", "John Doe")
                .start();

        Assertions.assertNotNull(caseInstance);
      }
    }

---

### Docusaurus Docs Cmmn Ch05 Deployment (`docs/docusaurus/docs/cmmn/ch05-Deployment.md`)

---
id: ch05-Deployment
title: Deployment
---

## External resources

Case definitions live in the Flowable database. These case definitions can reference delegation classes when using Service Tasks or Spring beans from the Flowable configuration file. These classes and the Spring configuration file have to be available to all CMMN engines that may execute the case definitions.

### Java classes

All custom classes that are used in your case definition (for example, PlanItemJavaDelegates used in Service Tasks) should be present on the engine’s classpath when an instance of the case is started.

During deployment of a case definition however, those classes don’t have to be present on the classpath. This means that your delegation classes don’t have to be on the classpath when deploying a new case definition, for example.

When you are using the demo setup and you want to add your custom classes, you should add a JAR containing your classes to the flowable-task or flowable-rest webapp lib. Don’t forget to include the dependencies of your custom classes (if any) as well. Alternatively, you can include your dependencies in the libraries directory of your Tomcat installation, ${tomcat.home}/lib (or similar place for other web containers).

### Using Spring beans from a case instance

When expressions or scripts use Spring beans, those beans have to be available to the engine when executing the case definition. If you are building your own webapp and you configure your CMMN engine in your context as described in [the spring integration section](cmmn/ch04-Spring.md#spring-integration), that is straightforward. But bear in mind that you also should update the Flowable task and rest webapps with that context if you use it.

## Versioning of case definitions

CMMN doesn’t have a notion of versioning. That is actually good, because the executable CMMN file will probably live in a version control system repository (such as Subversion, Git or Mercurial) as part of your development project. However, versions of case definitions are created in the engine as part of deployment. During deployment, Flowable will assign a version to the CaseDefinition before it is stored in the Flowable DB.

For each case definition in a deployment, the following steps are performed to initialize the properties key, version, name and id:

-   The case definition id attribute in the XML file is used as the case definition key property.

-   The case definition name attribute in the XML file is used as the case definition name property. If the name attribute is not specified, then the id attribute is used as the name.

-   The first time a case with a particular key is deployed, version 1 is assigned. For all subsequent deployments of case definitions with the same key, the version will be set 1 higher than the highest currently deployed version. The key property is used to distinguish case definitions.

Take for example the following case

    <definitions id="myDefinitions" >
      <case id="myCase" name="My important case" >
        ...

When deploying this case definition, the case definition in the database will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>676</p></td>
<td><p>myCase</p></td>
<td><p>My important case</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Suppose we now deploy an updated version of the same case (for example, changing some human tasks), but the id of the case definition remains the same. The case definition table will now contain the following entries:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>676</p></td>
<td><p>myCase</p></td>
<td><p>My important case</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>870</p></td>
<td><p>myCase</p></td>
<td><p>My important case</p></td>
<td><p>2</p></td>
</tr>
</tbody>
</table>

When the runtimeService.createCaseInstanceBuilder().caseDefinitionKey("myCase").start() is called, it will now use the case definition with version 2, as this is the latest version of the case definition.

Should we create a second case, as defined below and deploy this to Flowable, a third row will be added to the table.

    <definitions id="myNewDefinitions" >
      <case id="myNewCase" name="My important case" >
        ...

The table will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>676</p></td>
<td><p>myCase</p></td>
<td><p>My important case</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>870</p></td>
<td><p>myCase</p></td>
<td><p>My important case</p></td>
<td><p>2</p></td>
</tr>
<tr class="odd">
<td><p>1033</p></td>
<td><p>myNewCase</p></td>
<td><p>My important case</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Note how the key for the new case is different from our first case. Even though the name is the same (we should probably have changed that too), Flowable only considers the id attribute when distinguishing cases. The new case is therefore deployed with version 1.

## Category

Both deployments and case definitions have user-defined categories. The case definition category is initialized with the value of the targetNamespace attribute in the CMMN XML: &lt;definitions ... targetNamespace="yourCategory" ...

The deployment category can also be specified in the API like this:

    repositoryService
        .createDeployment()
        .category("yourCategory")
        ...
        .deploy();

---

### Docusaurus Docs Cmmn Ch06 Cmmn (`docs/docusaurus/docs/cmmn/ch06-cmmn.md`)

---
id: ch06-cmmn
title: CMMN 1.1
---

## What is CMMN?

The Case Management Model and Notation (CMMN) is a standard notation and formal specification by the [Object Management Group](http://www.omg.org/spec/CMMN/) for representing case models.

Flowable contains:

-   A CMMN 1.1 modeler to create CMMN 1.1 case models

-   A Java engine that can import and execute CMMN 1.1 case models

-   A demonstration UI that executes the case models, allowing users to see and complete human tasks (and their forms)

## Basic concepts and terminology

The following figure shows a simple CMMN 1.1 diagram:



A **case model** is always visualized as some sort of *folder* that contains all the case elements. Every case model contains a **plan model** onto which items will be *planned*.

The elements of a plan model are called **plan items**. Each *plan item* has a **plan item definition** that gives its type and possible configuration options at runtime. For example, in the figure above, there are three **human task** plan items and one **milestone**. Other examples of plan items are *process tasks, case tasks and stages*.

After having deployed a case model to the Flowable CMMN engine, it’s possible to start **case instances** based on this case model. The plan items defined in the case model similarly have **plan item instance** runtime representations that are exposed by, and can be queried using, the Flowable API. Plan item instances have a state lifecycle that is defined in the CMMN 1.1 specification and is core to how the engine works. Please check out section 8.4.2 of the CMMN 1.1 specification for all the details.

Plan items can have *sentries*: a plan item is said to have *entry criteria* when a sentry "guards" its activation. These criteria specify conditions that must be satisfied to *trigger the sentry*. For example, in the figure above, the "Milestone One" plan item is *available* after a case instance is started, but it is *activated* (in CMMN 1.1 specification terminology: it moves from the *available* state to the *active* state) when both human task A and B are completed. Note that sentries can have complex expression in their *if part*, which are not visualized, allowing for much more complex functionality. Also note that there can be multiple sentries, although only one needs to be satisfied to trigger a state transition.

Plan items and the plan model can also have sentries with *exit criteria*, which specify conditions that trigger an *exit* from that particular plan item. In the figure above, the whole plan model is exited (as are all the child elements that are active at that moment), when human task C completes.

CMMN 1.1 defines a standard XML format in an XSD that is part of the specification. For information, the example in the figure above is represented in XML as shown below.

Some observations:

-   The four plan items above are in the XML and they reference their definition with a *definitionRef*. The actual definitions are at the bottom of the *casePlanModel* element

-   The plan items have criteria (entry or exit) that reference a *sentry* (not the other way around)

-   The XML also contains information on how the diagram is visualized (x and y coordinates, widths and heights, and so on), which are omitted below. These elements are important when exchanging case models with other CMMN 1.1 modeling tools to preserve the correct visual representation



    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:flowable="http://flowable.org/cmmn"
                 xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
                 xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
                 xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
                 targetNamespace="http://www.flowable.org/casedef">
      <case id="simpleExample" name="Simple Example">
        <casePlanModel id="casePlanModel" name="My Case">
          <planItem id="planItem1" name="Human task A"
                definitionRef="sid-88199E7C-7655-439C-810B-8849FC52D3EB"></planItem>
          <planItem id="planItem2" name="Milestone One"
                definitionRef="sid-8BF8A774-A8A7-4F1A-95CF-1E0D61EE5A47">
            <entryCriterion id="sid-62CC4A6D-B29B-4129-93EA-460253C45CDF"
                sentryRef="sentry1"></entryCriterion>
          </planItem>
          <planItem id="planItem3" name="Human task B"
                definitionRef="sid-A1FB8733-0DBC-4B38-9830-CBC4D0C4B802"></planItem>
          <planItem id="planItem4" name="Human task C"
                definitionRef="sid-D3970AFC-7391-4BA7-95BA-51C64D2F41E9"></planItem>
          <sentry id="sentry1">
            <planItemOnPart id="sentryOnPart1" sourceRef="planItem1">
              <standardEvent>complete</standardEvent>
            </planItemOnPart>
            <planItemOnPart id="sentryOnPart2" sourceRef="planItem3">
              <standardEvent>complete</standardEvent>
            </planItemOnPart>
          </sentry>
          <sentry id="sentry2">
            <planItemOnPart id="sentryOnPart3" sourceRef="planItem4">
              <standardEvent>complete</standardEvent>
            </planItemOnPart>
          </sentry>
          <humanTask id="sid-88199E7C-7655-439C-810B-8849FC52D3EB"
            name="Human task A"></humanTask>
          <milestone id="sid-8BF8A774-A8A7-4F1A-95CF-1E0D61EE5A47"
            name="Milestone One"></milestone>
          <humanTask id="sid-A1FB8733-0DBC-4B38-9830-CBC4D0C4B802"
            name="Human task B"></humanTask>
          <humanTask id="sid-D3970AFC-7391-4BA7-95BA-51C64D2F41E9"
            name="Human task C"></humanTask>
          <exitCriterion id="sid-422626DB-9B40-49D8-955E-641AB96A5BFA"
            sentryRef="sentry2"></exitCriterion>
        </casePlanModel>
      </case>
      <cmmndi:CMMNDI>
        <cmmndi:CMMNDiagram id="CMMNDiagram_simpleExample">
            ...
        </cmmndi:CMMNDiagram>
      </cmmndi:CMMNDI>
    </definitions>

## Programmatic example

In this section we’re going to build a simple case model and execute it programmatically through the Java APIs of the Flowable CMMN engine in a simple command line example.

The case model we’ll build is a simplified *employee onboarding* case with two stages: a phase before and phase after the potential employee has started. In the first stage, someone from the HR department will complete the tasks, while in the second stage it is the employee completing them. Also, at any point in time, the potential employee can reject the job and stop the whole case instance.

Note that only stages and human tasks are used. In a real case model, there will most likely other plan item types too, such as milestones, nested stages, automated tasks, and so on.



The XML for this case model is the following:

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:flowable="http://flowable.org/cmmn"
                 xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
                 xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
                 xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
                 targetNamespace="http://www.flowable.org/casedef">
      <case id="employeeOnboarding" name="Simple Example">
        <casePlanModel id="casePlanModel" name="My Case">
          <planItem id="planItem5" name="Prior to starting"
                definitionRef="sid-025D29E8-BA9B-403D-A684-8C5B52185642"></planItem>
          <planItem id="planItem8" name="After starting"
                definitionRef="sid-8459EF32-4F4C-4E9B-A6E9-87FDC2299044">
            <entryCriterion id="sid-50B5F12D-FE75-4D05-9148-86574EE6C073"
                sentryRef="sentry2"></entryCriterion>
          </planItem>
          <planItem id="planItem9" name="Reject job"
                definitionRef="sid-134E885A-3D58-417E-81E2-66A3E12334F9"></planItem>
          <sentry id="sentry2">
            <planItemOnPart id="sentryOnPart4" sourceRef="planItem5">
              <standardEvent>complete</standardEvent>
            </planItemOnPart>
          </sentry>
          <sentry id="sentry3">
            <planItemOnPart id="sentryOnPart5" sourceRef="planItem9">
              <standardEvent>complete</standardEvent>
            </planItemOnPart>
          </sentry>
          <stage id="sid-025D29E8-BA9B-403D-A684-8C5B52185642" name="Prior to starting">
            <planItem id="planItem1" name="Create email address"
                    definitionRef="sid-EA434DDD-E1BE-4AC1-8520-B19ACE8782D2"></planItem>
            <planItem id="planItem2" name="Allocate office"
                    definitionRef="sid-505BA223-131A-4EF0-ABAD-485AEB0F2C96"></planItem>
            <planItem id="planItem3" name="Send joining letter to candidate"
                    definitionRef="sid-D28DBAD5-0F5F-45F4-8553-3381199AC45F">
              <entryCriterion id="sid-4D88C79D-8E31-4246-9541-A4F6A5720AC8"
                sentryRef="sentry1"></entryCriterion>
            </planItem>
            <planItem id="planItem4" name="Agree start date"
                    definitionRef="sid-97A72C46-C0AD-477F-86DD-85EF643BB97D"></planItem>
            <sentry id="sentry1">
              <planItemOnPart id="sentryOnPart1" sourceRef="planItem1">
                <standardEvent>complete</standardEvent>
              </planItemOnPart>
              <planItemOnPart id="sentryOnPart2" sourceRef="planItem2">
                <standardEvent>complete</standardEvent>
              </planItemOnPart>
              <planItemOnPart id="sentryOnPart3" sourceRef="planItem4">
                <standardEvent>complete</standardEvent>
              </planItemOnPart>
            </sentry>
            <humanTask id="sid-EA434DDD-E1BE-4AC1-8520-B19ACE8782D2"
                name="Create email address"
                flowable:candidateGroups="hr"></humanTask>
            <humanTask id="sid-505BA223-131A-4EF0-ABAD-485AEB0F2C96"
                name="Allocate office"
                flowable:candidateGroups="hr"></humanTask>
            <humanTask id="sid-D28DBAD5-0F5F-45F4-8553-3381199AC45F"
                name="Send joining letter to candidate"
                flowable:candidateGroups="hr"></humanTask>
            <humanTask id="sid-97A72C46-C0AD-477F-86DD-85EF643BB97D"
                name="Agree start date"
                flowable:candidateGroups="hr"></humanTask>
          </stage>
          <stage id="sid-8459EF32-4F4C-4E9B-A6E9-87FDC2299044"
            name="After starting">
            <planItem id="planItem6" name="New starter training"
                    definitionRef="sid-DF7B9582-11A6-40B4-B7E5-EC7AC6029387"></planItem>
            <planItem id="planItem7" name="Fill in paperwork"
                    definitionRef="sid-7BF2B421-7FA0-479D-A8BD-C22EBD09F599"></planItem>
            <humanTask id="sid-DF7B9582-11A6-40B4-B7E5-EC7AC6029387"
                name="New starter training"
                flowable:assignee="${potentialEmployee}"></humanTask>
            <humanTask id="sid-7BF2B421-7FA0-479D-A8BD-C22EBD09F599"
                name="Fill in paperwork"
                flowable:assignee="${potentialEmployee}"></humanTask>
          </stage>
          <humanTask id="sid-134E885A-3D58-417E-81E2-66A3E12334F9" name="Reject job"
            flowable:assignee="${potentialEmployee}"></humanTask>
          <exitCriterion id="sid-18277F30-E146-4B3E-B3C9-3F1E187EC7A8"
            sentryRef="sentry3"></exitCriterion>
        </casePlanModel>
      </case>
    </definitions>

First of all, create a new project and add the *flowable-cmmn-engine* dependency (here shown for Maven). The H2 dependency is also added, as H2 will be used as embedded database later on.

    <dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable-cmmn-engine</artifactId>
        <version>${flowable.version}</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>${h2.version}</version>
    </dependency>

The Flowable CMMN API is designed to be consistent with the other Flowable APIs and concepts. As such, people that know the BPMN or DMN APIs will have no problem finding their way around. As with the other engines, the first line of code is creating a CmmnEngine. Here, the default in-memory configuration is used, which uses H2 as the database:

    public class Main {
      public static void main(String[] args) {
        CmmnEngine cmmnEngine
            = new StandaloneInMemCmmnEngineConfiguration().buildCmmnEngine();
      }
    }

Note that the *CmmnEngineConfiguration* exposes many configuration options for tweaking various settings of the CMMN engine.

Put the XML from above in a file, for example *my-case.cmmn* (or .cmmn.xml). For Maven, it should be placed in the *src/main/resources* folder.

To make the engine aware of the case model, it first needs to be *deployed*. This is done through the *CmmnRepositoryService*:

    CmmnRepositoryService cmmnRepositoryService = cmmnEngine.getCmmnRepositoryService();
    CmmnDeployment cmmnDeployment = cmmnRepositoryService.createDeployment()
        .addClasspathResource("my-case.cmmn")
        .deploy();

Deploying the XML will return a **CmmnDeployment**. A deployment can contain many case models and artifacts. The specific case model definition above is stored as a **CaseDefinition**. This can be verified by doing a *CaseDefinitionQuery*:

    List<CaseDefinition> caseDefinitions = cmmnRepositoryService.createCaseDefinitionQuery().list();
    System.out.println("Found " + caseDefinitions.size() + " case definitions");

Having a **CaseDefinition** in the engine, it’s now possible to start a **CaseInstance** for this case model definition. Either the result from the query is used and passed into the following snippet of code, or the *key* of the case definition is used directly (as done below).

Note that we’re also passing data, an identifier to the *potentialEmployee* as a variable when starting the **CaseInstance**. This variable will later be used in the human tasks to assign the task to the correct person (see the *assignee="${potentialEmployee}"* attribute on *human tasks*).

    CmmnRuntimeService cmmnRuntimeService = cmmnEngine.getCmmnRuntimeService();
    CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
        .caseDefinitionKey("employeeOnboarding")
        .variable("potentialEmployee", "johnDoe")
        .start();

After the **CaseInstance** is started, the engine will determine which of the plan items of the model should be activated:

-   The first stage has no entry criteria, so it’s activated

-   The child human tasks of the first stage have no entry criteria, so three of them are expected to be active

The plan items are represented at runtime by **PlanItemInstances** and can be queried through the *CmmnRuntimeService*:

    List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
        .caseInstanceId(caseInstance.getId())
        .orderByName().asc()
        .list();

    for (PlanItemInstance planItemInstance : planItemInstances) {
        System.out.println(planItemInstance.getName());
    }

which prints out

    After starting
    Agree start date
    Allocate office
    Create email address
    Prior to starting
    Reject job
    Send joining letter to candidate

Some things might be unexpected here:

-   The stages are *also* plan items and thus have a representation as **PlanItemInstance**. Note that that child plan item instances will have the stage as parent when calling *.getStageInstanceId()*.

-   The *Send joining letter to candidate* is returned in the result. The reason is that, in accordance with the CMMN 1.1 specification, this plan item instance is in the *available* state, but not yet in the *active* state.

Indeed, when the code above is changed to

    for (PlanItemInstance planItemInstance : planItemInstances) {
        System.out.println(planItemInstance.getName()
            + ", state=" + planItemInstance.getState()
            + ", parent stage=" + planItemInstance.getStageInstanceId());
    }

The output now becomes:

    After starting, state=available, parent stage=null
    Agree start date, state=active, parent stage=fe37ac97-b016-11e7-b3ad-acde48001122
    Allocate office, state=active, parent stage=fe37ac97-b016-11e7-b3ad-acde48001122
    Create email address, state=active, parent stage=fe37ac97-b016-11e7-b3ad-acde48001122
    Prior to starting, state=active, parent stage=null
    Reject job, state=active, parent stage=fe37ac97-b016-11e7-b3ad-acde48001122
    Send joining letter to candidate, state=available, parent stage=fe37ac97-b016-11e7-b3ad-acde48001122

To only show the active plan item instances, the query can be adapted by adding *planItemInstanceStateActive()*:

     List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
        .caseInstanceId(caseInstance.getId())
        .planItemInstanceStateActive()
        .orderByName().asc()
        .list();

The output is now

    Agree start date
    Allocate office
    Create email address
    Prior to starting
    Reject job

Of course, the **PlanItemInstance** is the low level representation, but each plan item also has a *plan item definition* that defines what type it is. In this case, we only have *human tasks*. It is possible to interact with the *CaseInstance* via its *plan item instances*, for example by triggering them programmatically (for example, *CmmnRuntimeService.triggerPlanItemInstance(String planItemInstanceId)*). However, most likely the interaction will happen through the results of the actual plan item definition: here, the human tasks.

Querying for tasks is done in the exact same way as for the BPMN engine (in fact, the task service is a shared component and tasks created in BPMN or CMMN can be queried through both engines):

    CmmnTaskService cmmnTaskService = cmmnEngine.getCmmnTaskService();
    List<Task> hrTasks = cmmnTaskService.createTaskQuery()
        .taskCandidateGroup("hr")
        .caseInstanceId(caseInstance.getId())
        .orderByTaskName().asc()
        .list();
    for (Task task : hrTasks) {
        System.out.println("Task for HR : " + task.getName());
    }

    List<Task> employeeTasks = cmmnTaskService.createTaskQuery()
        .taskAssignee("johndoe")
        .orderByTaskName().asc()
        .list();
    for (Task task : employeeTasks) {
        System.out.println("Task for employee: " + task);
    }

Which outputs:

    Task for HR : Agree start date
    Task for HR : Allocate office
    Task for HR : Create email address

    Task for employee: Reject job

When the three tasks of HR are completed, the 'Send joining letter to candidate' task should be available:

    for (Task task : hrTasks) {
        cmmnTaskService.complete(task.getId());
    }

    hrTasks = cmmnTaskService.createTaskQuery()
        .taskCandidateGroup("hr")
        .caseInstanceId(caseInstance.getId())
        .orderByTaskName().asc()
        .list();

    for (Task task : hrTasks) {
        System.out.println("Task for HR : " + task.getName());
    }

And indeed, the expected task is now created:

    Task for HR : Send joining letter to candidate

Completing this task will now move the case instance into the second stage, as the sentry for the first stage is satisfied. The 'Reject job' tasks is automatically completed by the system and the two tasks for the employee are created:

    Task for employee: Fill in paperwork
    Task for employee: New starter training
    Task for employee: Reject job

Completing all the tasks will end the case instance:

    List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).listPage(0, 1);
    while (!tasks.isEmpty()) {
        cmmnTaskService.complete(tasks.get(0).getId());
        tasks = cmmnTaskService.createTaskQuery()
            .caseInstanceId(caseInstance.getId())
            .listPage(0, 1);
    }

While executing case instances, the engine also stores historic information, which can be queried via a query API:

    CmmnHistoryService cmmnHistoryService = cmmnEngine.getCmmnHistoryService();
    HistoricCaseInstance historicCaseInstance = cmmnHistoryService.createHistoricCaseInstanceQuery()
        .caseInstanceId(caseInstance.getId())
        .singleResult();

    System.out.println("Case instance execution took "
        + (historicCaseInstance.getEndTime().getTime() - historicCaseInstance.getStartTime().getTime()) + " ms");

    List<HistoricTaskInstance> historicTaskInstances = cmmnHistoryService.createHistoricTaskInstanceQuery()
        .caseInstanceId(caseInstance.getId())
        .orderByTaskCreateTime().asc()
        .list();

    for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
        System.out.println("Task completed: " + historicTaskInstance.getName());
    }

Which outputs:

    Case instance execution took 149 ms
    Task completed: Reject job
    Task completed: Agree start date
    Task completed: Allocate office
    Task completed: Create email address
    Task completed: Send joining letter to candidate
    Task completed: New starter training
    Task completed: Fill in paperwork

Historic data related to the case execution is collected for special constructs, such as Tasks (as seen above), milestones, cases, variables and plan items in general.
This data is persisted at the same time as the runtime data, but it is not deleted when case instances end.
Access to the historic data is provided as query APIs by the *CmmnHistoryService*

Of course, this is but a small part of the available APIs and constructs available in the Flowable CMMN Engine. Please check the other sections for more detailed information

## CMMN 1.1 Constructs

This chapter covers the CMMN 1.1 constructs supported by Flowable, as well as extensions to the CMMN 1.1 standard.

The following constructs, with the exception of sentries and item control, as for the CMMN specification are considered plan items.
Historic data of their instances execution can be queried through the *CmmnHistoryService* using *org.flowable.cmmn.api.history.HistoricPlanItemInstanceQuery*.

### Stage

A stage is used to group plan items together. It is typically used to define "phases" in a case instance.

A stage is a plan item itself, and thus can have entry and exit criteria. Plan items contained within a stage are only available when the parent stage moves to the *active* state. Stages can be nested in other stages.

A stage is visualized as a rectangle with angled corners:



### Task

A "manual" task, meaning the task will happen external to the engine.

Properties:

-   **name**: expression that will be resolved at runtime as the name of the manual task

-   **blocking**: a boolean value determining whether the task blocks

-   **blockingExpression**: an expression that evaluates to a boolean indicating whether the tasks blocks

If a task is non-blocking, the engine will simply complete it automatically when executing it. If a task is blocking, a *PlanItemInstance* for this task will remain in the *active* state until it is programmatically triggered by the *CmmnRuntimeService.triggerPlanItemInstance(String planItemInstanceId)* method.

A task is visualized as a rounded rectangle:



### Human task

A human task is used to model work that needs to be done by a human, typically through a form. When the engine arrives at a human task, a new entry is created in the task list of any users or groups assigned to that task.

A human task is a plan item, which means that beyond a human task entry also a *PlanItemInstance* is created and it can be queried via the *PlanItemInstanceQuery*.

Human tasks can be queried through the *org.flowable.task.api.TaskQuery* API. Historic task data can be queried through the *org.flowable.task.api.history.HistoricTaskInstanceQuery*.

Properties:

-   **name**: expression that will be resolved at runtime as the name of the human task

-   **blocking**: a boolean value determining whether the task blocks

-   **blockingExpression**: an expression that evaluates to a boolean indicating whether the tasks blocks

-   **assignee** : an expression (can be a static text value) that is used to determine to whom the human task is assigned

-   **owner** : an expression (can be a static text value) that is used to determine who is the owner of the human task

-   **candidateUsers** : an expression (can be a static text value) that resolves to a comma-separated list of Strings that is used to determine which users are candidate for this human task

-   **candidateGroups** : an expression (can be a static text value) that resolves to a comma-separated list of Strings that is used to determine to which groups the task is assigned

-   **form key**: an expression that determines a key when using forms. Can be retrieved via the API afterwards

-   **Due date** an expression that resolves to java.util.Date or a ISO-8601 date string

-   **Priority**: an expression that resolves to an integer. Can be used in the TaskQuery API to filter tasks

A human task is visualized as a rounded rectangle with a user icon in the top left corner:



### Java Service task

A service task is used to execute custom logic.

Custom logic is placed in a class that implements the *org.flowable.cmmn.api.delegate.PlanItemJavaDelegate* interface.

    public class MyJavaDelegate implements PlanItemJavaDelegate {

        public void execute(DelegatePlanItemInstance planItemInstance) {
            String value = (String) planItemInstance.getVariable("someVariable");
            ...
        }

    }

For lower-level implementations that cannot be covered by using the *PlanItemJavaDelegate* approach, the *CmmnActivityBehavior* can be used (similar to *JavaDelegate* vs *ActivityBehavior* in the BPMN engine).

Properties:

-   **name**: name of the service task

-   **class**: the Java class implementing the custom logic

-   **class fields**: parameters to pass when calling the custom logic

-   **Delegate expression**: an expression that resolves to a class implementing the *PlanItemJavaDelegate* interface

A service task is visualized as a rounded rectangle with a cog icon in the top left corner:



### External Worker Task

#### Description

The External Worker Task allows you to create jobs that should be acquired and executed by External Workers.
An External Worker can acquire jobs over the Java API or REST API.
This is similar to an async Service Task.
The difference is that instead of Flowable executing the logic,
an External Worker, which can be implemented in any language, queries Flowable for jobs, executes them and sends the result to Flowable.
Note that the External Worker task is **not** an 'official' task of CMMN spec (and doesn’t have a dedicated icon as a consequence).

#### Defining an External Worker Task

The External Worker task is implemented as a dedicated [Task](cmmn/ch06-cmmn.md#task) and is defined by setting *'external-worker'* for the *type* of the task.

```xml
<task id="externalWorkerOrder" flowable:type="external-worker">
```

The External Worker task is configured by setting the `topic` (can be an EL expression) which the External Worker uses to query for jobs to execute.

#### Example usage

The following XML snippet shows an example of using the External Worker Task.
The External Worker is a wait state.
When the execution reaches the task it will create an External Worker Job, which can be acquired by an External Worker.
Once the External Worker is done with the job and notifies Flowable of the completion the execution of the case will continue.


```xml
<task id="externalWorkerOrder" flowable:type="external-worker" flowable:topic="orderService" />
```

#### Acquiring External Worker Job

External Worker Jobs are acquired via the `CmmnManagementService#createExternalWorkerJobAcquireBuilder` by using a `ExternalWorkerJobAcquireBuilder`

```java
List<AcquiredExternalWorkerJob> acquiredJobs = cmmnManagementService.createExternalWorkerJobAcquireBuilder()
                .topic("orderService", Duration.ofMinutes(30))
                .acquireAndLock(5, "orderWorker-1");
```

By using the above Java snippet External Worker jobs can be acquired.
With the snippet we did the following:

* Query for External Worker Jobs with the topic *orderService*.
* Acquire and lock the jobs for 30 minutes waiting for the completion signal from the External Worker.
* Acquire maximum of 5 jobs
* The owner of the jobs is the worker with id *orderWorker-1*

An `AcquiredExternalWorkerJob` also has access to the Case variables.
When the External Worker Task is exclusive, acquiring the job will lock the Case Instance.

#### Completing an External Worker Job

External Worker Jobs are completed via the `CmmnManagementService#createCmmnExternalWorkerTransitionBuilder(String, String)` by using a `CmmnExternalWorkerTransitionBuilder`

```java
cmmnManagementService.createCmmnExternalWorkerTransitionBuilder(acquiredJob.getId(), "orderWorker-1")
                .variable("orderStatus", "COMPLETED")
                .complete();
```

A Job can be completed only by the worker that acquired it. Otherwise a `FlowableIllegalArgumentException` will be thrown.

Using the snippet above the task is completed and the case execution will continue.
The continuation of the execution is done asynchronously in a new transaction.
This means that completing an external worker task will only create an asynchronous (new) job to execute the completion (and the current thread returns after doing that).
Any steps in the model that follow after the external worker task will be executed in that transaction, similar to a regular async service task.

It is also possible to use `CmmnExternalWorkerTransitionBuilder#terminate()` to transition the external worker job.

#### Error handling for an External Worker Job

The `ExternalWorkerJobFailureBuilder` is used to fail a job (schedule it for a new execution in the future)

In order to fail a job the following can be used:


```java
cmmnManagementService.createExternalWorkerJobFailureBuilder(acquiredJob.getId(), "orderWorker-1")
                .errorMessage("Failed to run job. Database not accessible")
                .errorDetails("Some complex and long error details")
                .retries(4)
                .retryTimeout(Duration.ofHours(1))
                .fail();
```

With this snippet the following will be done:

* The error message and error details will be set on the job
* The retry count for the job will be set to 4
* The job will be available for acquiring after 1 hour

The Job can only be failed by the worker that acquired it.
If no retries have been set, flowable will automatically decrease the number of retries for a job by 1.
When the number of retries is 0 the job will be moved to the DeadLetter table job and will no longer be available for acquiring.

#### Querying External Worker Jobs

External Worker Jobs are queried by using the `ExternalWorkerJobQuery` by creating it via `CmmnManagementService#createExternalWorkerJobQuery`.

### Decision task

A *Decision task* calls out to a DMN decision table and stores the resulting variable in the case instance.

Properties:

-   **Decision table reference**: the referenced DMN decision table that needs to be invoked.

It is also possible to throw an error when no rule is hit during the evaluation of the DMN decision table by setting the '*Throw error if no rules were hit*' property.

A decision task is visualized as a *task* with a table icon in the top left corner:



### Http Task

The Http task is an out-of-the-box implementation of a *service task*. It is used when a REST service needs to be called over HTTP.

The Http task has various options to customize the request and response. See the BPMN http task documentation for details on all the configuration options.

A http task is visualized as a *task* with a rocket icon in the top left corner:



### Script Task

A task of type "script", similar to its equivalent in BPMN, the Script Task executes a script when the plan item instance becomes active.

Properties:

-   **name**: task attribute to indicate the name of the task

-   **type**: task attribute whose value must be "script" to indicate the type of task

-   **scriptFormat**: extended attribute that indicate the language of the script (for example, javascript, groovy)

-   **script**: the script to execute, defined as a string in a field element named "script"

-   **autoStoreVariables**: optional task attribute flag (default: false) that indicates whether or not variables defined in the script will be stored in the Plan Item Instance context (see note below)

-   **resultVariableName**: optional task attribute that when present will store a variable with the specified name in the Plan Item instance context with the script evaluation result (see note below)

A script task is visualized as a *task* with a script icon in the top left corner:



    <planItem id="scriptPlanItem" name="Script Plan Item" definitionRef="myScriptTask" />
    <task name="My Script Task Item" flowable:type="script" flowable:scriptFormat="JavaScript">
        <documentation>Optional documentation</documentation>
        <extensionElements>
            <flowable:field name="script">
                <string>
                    sum = 0;
                    for ( i in inputArray ) {
                        sum += i;
                    }
                </string>
            </flowable:field>
        </extensionElements>
    </task>

**Note**: The value of the **scriptFormat** attribute must be a name that is compatible with the [JSR-223](http://jcp.org/en/jsr/detail?id=223) (scripting for the Java platform). By default, JavaScript is included in every JDK and as such doesn’t need any additional JAR files. If you want to use another (JSR-223 compatible) scripting engine, it is sufficient to add the corresponding JAR to the classpath and use the appropriate name. For example, the Flowable unit tests often use Groovy because the syntax is similar to that of Java.

Do note that the Groovy scripting engine is bundled with the groovy-jsr223 JAR. As such, one must add the following dependency:

    <dependency>
        <groupId>org.apache.groovy</groupId>
        <artifactId>groovy-jsr223</artifactId>
        <version>4.x.x<version>
    </dependency>

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

    <flowable:field name="script">
        <string>
        sum = 0
        for ( i in inputArray ) {
          sum += i
        }
        </string>
    </flowable:field>

**Note**: It’s also possible to set plan item instance variables in a script, simply by calling *planItemInstance.setVariable("variableName", variableValue)*. By default, no variables are stored automatically. It’s possible to automatically store any variable defined in the script (for example, *sum* in the example above) by setting the property autoStoreVariables on the scriptTask to true. However, **the best practice is not to do this and use an explicit planItemInstance.setVariable() call**, as with some recent versions of the JDK, auto storing of variables does not work for some scripting languages. See [this link](http://www.jorambarrez.be/blog/2013/03/25/bug-on-jdk-1-7-0_17-when-using-scripttask-in-activiti/) for more details.

    <task name="Script Task" flowable:type="script" flowable:scriptFormat="groovy" flowable:autoStoreVariables="false">

The default for this parameter is false, meaning that if the parameter is omitted from the script task definition, all the declared variables will only exist during the duration of the script.

Here’s an example of how to set a variable in a script:

    <flowable:field name="script">
        <string>
        def scriptVar = "test123"
        planItemInstance.setVariable("myVar", scriptVar)
        </string>
    </flowable:field>

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

**Note** The return value of a script task can be assigned to an already existing or new plan item instance variable by specifying its name as a literal value for the *'flowable:resultVariable'* attribute of a script task definition. Any existing value for a specific plan item instance 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.

    <task name="Script Task" flowable:type="script" flowable:scriptFormat="groovy" flowable:resultVariable="myVar">
        <flowable:field name="script">
            <string>#{echo}</string>
        </flowable:field>
    </task>

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.

### Milestone

A milestone is used to mark arriving at a certain point in the case instance. At runtime, they are represented as **MilestoneInstances** and they can be queried through the **MilestoneInstanceQuery** via the *CmmnRuntimeService*. There is also a historical counterpart via the *CmmnHistoryService*.

A milestone is a plan item, which means that as well as a milestone entry, a *PlanItemInstance* is created also, which can be queried via the *PlanItemInstanceQuery*.

Properties:

-   **name**: an expression or static text that determines the name of the milestone

A milestone is visualized as a rounded rectangle (more rounded than a task):



### Case task

A case task is used to start a child case within the context of another case. The *CaseInstanceQuery* has *parent* options to find these cases.

When the case task is blocking, the *PlanItemInstance* will be *active* until the child case has completely finished. If the case task is non-blocking, the child case is started and the plan item instance automatically completes. When the child case instance ends there is no impact on the parent case.

Properties:

-   **name**: an expression or static text that determines the name

-   **blocking**: a boolean value determining whether the task blocks

-   **blockingExpression**: an expression that evaluates to a boolean indicating whether the tasks blocks

-   **Case reference**: the key of the case definition that is used to start the child case instance. Can be an expression

A case task is visualized as a rounded rectangle with a case icon in the top left corner:



### Process task

A process task is used to start a process instance within the context of a case.

When the process task is blocking, the *PlanItemInstance* will be *active* until the process instance has completely finished. If the process task is non-blocking, the process instance is started and the plan item instance automatically completes. When the process instance ends there is no impact on the parent case.

Properties:

-   **name**: an expression or static text that determines the name

-   **blocking**: a boolean value determining whether the task blocks

-   **blockingExpression**: an expression that evaluates to a boolean indicating whether the tasks blocks

-   **Process reference**: the key of the process definition that is used to start the process instance. Can be an expression

A process task is visualized as a rounded rectangle with an arrow icon in the top left corner:



A process task can be configured to have in- and out parameters, which take the form of *source/sourceExpression* and *target/targetExpression*.

The in parameters are resolved within context of the case instance.

-   The *source* value will be the case instance variable which value will be mapped to a process variable

-   Alternatively, the *sourceExpression* allows to create an arbitrary value, where the expression is resolved against the case instance.

-   The *target* will be the name of the process variable to which the source value is mapped.

-   Alternatively, the *targetExpression* will resolve to a **string** value that is used as variable name in the process instance. The expression is resolved within case instance context.

The out parameters are resolved within context of the process instance.

-   The *source* value will be the process instance variable which value will be mapped to a case variable

-   Alternatively, the *sourceExpression* allows to create an arbitrary value, where the expression is resolved against the process instance.

-   The *target* will be the name of the case variable to which the source value is mapped.

-   Alternatively, the *targetExpression* will resolve to a **string** value that is used as variable name in the case instance. The expression is resolved within process instance context.

### Criteria

#### Entry criterion (entry sentry)

Entry criteria form a sentry for a given plan item instance. They consist of two parts:

-   One or more parts that depend on other plan items: these define dependencies on state transitions of other plan items. For example, one human task can depend on the state transition 'complete' of three other human tasks to become active itself

-   One optional *if part* or *condition*: this is an expression that allows the definition of a complex condition

A sentry is satisfied when all its criteria are resolved to *true*. When a criterion evaluates to true, this is stored and remembered for future evaluations. Note that entry criteria of all plan item instances in the *available* state are evaluated whenever something changes in the case instance.
Multiple sentries are possible on a plan item. However, when one is satisfied, the plan item moves from state *available* to *active*.

See [the section on sentry evaluation](cmmn/ch06-cmmn.md#sentry-evaluation) for more information.

An entry criterion is visualized as a diamond shape (white color inside) on the border of a plan item:



#### Exit criterion (exit sentry)

Exit criteria form a sentry for a given plan item instance. They consist of two parts:

-   One or more parts that depend on other plan items: these define dependencies on state transitions of other plan items. For example, one human task can depend on reaching a certain milestone to be automatically terminated

-   One optional *if part* or *condition*: this is an expression that allows a complex condition to be defined

A sentry is satisfied when all its criteria are resolved to *true*. When a criterion evaluates to true, this is stored and remembered for future evaluations. Note that exit criteria of all plan item instances in the *active* state are evaluated whenever something changes in the case instance.
Multiple sentries are possible on a plan item. However, when one is satisfied, the plan item moves from state *active* to *exit*.

See [the section on sentry evaluation](cmmn/ch06-cmmn.md#sentry-evaluation) for more information.

An exit criterion is visualized as a diamond shape (white color inside) on the border of a plan item:



Beyond the specification, Flowable supports additional attributes on an exit sentry which adds more flexibility and options on how a plan item is terminated when the exit sentry triggers.

##### exitType

This attribute can be used for exit sentries on plan items, not stages or the case plan model though, and helps define how to exit the plan item.
It particularly makes sense in combination with repetition. A possible use case might be that you want to terminate active instances of a repetitive plan item, but maybe later on it becomes available again as the conditions change in the case. With the exit type other than the default, this is possible as the plan item is not terminated for good, but only active or active and enabled instances.

Possible values are:

-   **default**: The default exit type works as the spec says, it will terminate (exit) the plan item and all not yet finished instances as well.

-   **activeInstances**: If this exit type is chosen, the exit sentry only terminates active instances, but leaves enabled, available ones in place, so they can become active later on.

-   **activeAndEnabledInstances**: In addition to the previous one, this exit type also terminates enabled instances (e.g. ready for manual activation), but leaves available ones in place.

Example of an extended exit sentry on a human task:

    <planItem id="planItem1" name="Task 1" definitionRef="humanTask1">
        <itemControl>
            <repetitionRule></repetitionRule>
        </itemControl>
        <exitCriterion id="exitCriterion1" sentryRef="sentry1" flowable:exitType="activeAndEnabledInstances"></exitCriterion>
    </planItem>

##### exitEventType

This attribute can be used for exit sentries on stages or the case plan model as it offers an alternative exit than terminate. Imagine a stage where you don’t want to put autocompletion on, but rather have a user listener becoming available whenever the stage is completable and let the user decide when the stage should actually complete by triggering an exit sentry on the stage.
Using this combination according to spec will exit the stage and leave it in terminated state and triggering the exit event for further processing.
Maybe not what you want. With the *exitEventType* you can specify how the stage is exiting other than the default behavior.

Possible values are:

-   **exit** This is the default behavior compliant to the spec. It will terminate the stage and all of its children and leave it *terminated* state, using *exit* as the event type being triggered.

-   **complete** This value can be used to terminate the stage, but leave it in *completed* state (instead of *terminated*) and trigger the *complete* event, instead of the *exit* one. Basically, this behavior is exactly the same as if the stage would have been auto-completed. The engine will throw an exception, if the stage is not completable at the moment the exit sentry with this exit event type is triggered.

-   **forceComplete** This value is similar to the *complete* one, but does not check the stage to be completable upfront, but forces it to complete, even if there are still active child plan items at the moment the exit sentry is triggered. They will be terminated first, then the stage completes with *complete* event and be left in *completed* state.

Full example on how to use the exit event type attribute in combination with a user listener to manually complete the stage.
It contains two important parts: the *flowable:exitEventType="complete"* attribute on the exit criterion and the *flowable:availableCondition="${cmmn:isStageCompletable()}"* on the user event listener which makes the listener only available, if the stage is currently completable, otherwise it is unavailable.
Once the user listener triggers, the exit sentry is executed and will complete the stage, not terminate it and leave it in *completed* state, triggering the *complete* event, not the *exit* event.



Here you find the CMMN model in XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:flowable="http://flowable.org/cmmn"
                 xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI"
                 xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
                 xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI"
                 xmlns:design="http://flowable.org/design"
                 targetNamespace="http://flowable.org/cmmn">
      <case id="stageWithUserListenerForCompletion" name="Stage with user listener for completion">
        <casePlanModel id="casePlanModel1" name="Case plan model">
          <planItem id="planItem4" definitionRef="expandedStage1">
            <exitCriterion id="exitCriterion1" flowable:sentryRef="sentry1" flowable:exitEventType="complete"></exitCriterion>
          </planItem>
          <sentry id="sentry1">
            <planItemOnPart id="sentryOnPart1" sourceRef="planItem3">
              <standardEvent>occur</standardEvent>
            </planItemOnPart>
          </sentry>
          <stage id="expandedStage1" name="Stage A">
            <planItem id="planItem1" name="Task A" definitionRef="humanTask1"></planItem>
            <planItem id="planItem2" name="Task B" definitionRef="humanTask2">
              <itemControl>
                <repetitionRule></repetitionRule>
                <manualActivationRule></manualActivationRule>
              </itemControl>
            </planItem>
            <planItem id="planItem3" name="Complete stage" definitionRef="userEventListener1"></planItem>
            <humanTask id="humanTask1" name="Task A"></humanTask>
            <humanTask id="humanTask2" name="Task B"></humanTask>
            <userEventListener id="userEventListener1" name="Complete stage" flowable:availableCondition="${cmmn:isStageCompletable()}"></userEventListener>
          </stage>
        </casePlanModel>
      </case>
    </definitions>

### Event Listeners

#### Timer Event Listener

A timer event listener is used when the passing of time needs to be captured in a case model.

A timer event listener is not a task and has a simpler plan item lifecycle compared to a *task*: the timer will simply move from *available* to *completed* when the event (in this case, the time passing) occurs.

Properties:

-   **Timer expression**: an expression that defines when the timer should occur. The following options are possible:

    -   An expression resolving to a java.util.Date or org.joda.time.DateTime instance (for example, \_${someBean.calculateNextDate(someCaseInstanceVariable)})

    -   An ISO8601 date

    -   An ISO8601 duration String (for example, *PT5H*, indicating the timer should fire in 5 hours from instantiation)

    -   AN ISO8601 repetition String (for example, R5/PT2H, indicating the timer should fire 5 times, each time waiting 2 hours)

    -   A String containing a cron expression

-   **Start trigger plan item/event**: reference to a plan item in the case model that triggers the start of the timer event listener

Note that setting a *start trigger* for the timer event listener does not have a visual indicator in the case model, unlike entry/exit criteria on sentries.

A timer event listener is visualized as circle with a clock icon inside:



#### User Event Listener

A user event listener can be used when needing to capture a user interaction that directly influences a case state,
instead of indirectly via impacting variables or information in the case.
A typical use case for a user event listener are buttons in a UI that a user can click to drive the state of the case instance.
When the event is triggered an *Occur* event is thrown to which sentries can listener to.
Like timer event listeners, it has a much simpler lifecycle that a *task*.



User event listeners can be queried using the *org.flowable.cmmn.api.runtime.UserEventListenerInstanceQuery*. Such a query can be created by calling the *cmmnRuntimeService.createUserEventListenerInstanceQuery()* method. Note that a user event listener is also a plan item instance, which means it can also be queried through the *org.flowable.cmmn.api.runtime.PlanItemInstanceQuery* API.

A user event listener can be completed by calling the *cmmnRuntimeService.completeUserEventListenerInstance(id)* method.

#### Generic Event Listener

A generic event listener is used to typically model a programmatic interaction (e.g. a external system that calls out to change something in a case instance).



The API to retrieve and complete these event listeners is on the *CmmnRuntimeService*:

    GenericEventListenerInstanceQuery createGenericEventListenerInstanceQuery();
    void completeGenericEventListenerInstance(String genericEventListenerInstanceId);

Similar to *user event listeners*, this API is a wrapper on top of the *PlanItemInstance* queries and operations. This means that the data can also be retrieved through the regular *PlanItemInstanceQuery*

Note that generic event listeners are not part of the CMMN specification, but are a Flowable-specific addition.

#### Automatic removal of event listeners

The engine will automatically detect when event listeners (user or timer) are not useful anymore.
Take for example the following case definition:



Here, the *First stage* contains two human tasks (A and B) and it can be exited by a user when the *Stop first stage* user event is triggered.
However, when both tasks A and B are completed, the stage will also complete. If now the user event listener would be triggered, there is nothing that listens to this event anymore.
The engine will detect this and terminate the user event automatically.

The same mechanism also works for event listeners that are referenced by entry sentries:



In this case, in the case that *EventListenerA* would be triggered, *EventListenerB* is terminated (as nothing is listening to its occurrence anymore).

Or, when timer and user event listeners are mixed, the one that is triggered first will also cause the removal of others (when they are not referenced somewhere else):



Here, the timer will be removed in case the user event is triggered first (and vice versa).

The detection also takes in account plan items that have not yet been created. Take for example the following case definition:



Here, human task *C* is not yet created when a case instance is started for this case definition. The user event listener will not be removed as long that *C* has a parent stage that is in a non-terminal state, as this means that the event could still be listened to in the future.

#### Available condition

All types of event listeners can be configured to have a **available condition**: an expressions that will guard the available state of the event listener. To explain the use case, take the following case definition:



When the case instance is started, Stage 1 (as it has no entry criteria) will be moving immediately from *available* to *active*. Similar story for human task A. Human task B will move from *available* to *enabled* as it’s manually activated.

Normally, also the event listener would become *available*. The life cycle of event listeners is simpler than that of plan items such as human tasks: an event listener stays in the *available* state until the event happens. There’s no *active* state like for other plan items.
This means that a user could trigger it after start and the stage would be exited.

In some use case however, the event listener shouldn’t be *available* for the user to interact with (or a timer shouldn’t start, when using a timer event listener) unless a certain condition is true.

In the example above, we want to only create it when the stage doesn’t have any active children (or required) anymore. Setting the **availableCondition** to **${cmmn:isStageCompletable()}** will allow the event listener to be created which makes it move immediately to *available*. Concretely in this model, when human task A is completed Stage 1 becomes *completable* (as human task B is manually activated and non-required). This makes the *availableCondition* of the event listener *true* and the event listener is now available for a user to decide to exit the stage.

Note: this is a Flowable specific addition to the CMMN specification. Without this addition, the event listener would have to be nested within a substage which is protected with entry criteria that listens to the completion of task A.

Note: if this were an autocompletable stage, the engine would complete the stage automatically when A completes.

### Item control: Repetition Rule

Plan items on the case model can have a *repetition rule*: an expression that can be used to indicate a certain plan item needs to be repeated.
When no expression is set, but the repetition is enabled (for example, the checkbox is checked in the Flowable Modeler) or the expression is empty, a *true* value is assumed by default.

An optional *repetition counter variable* can be set, which holds the index (one-based) of the instance. If not set, the default variable name is *repetitionCounter*.

If the plan item does not have any entry criteria, the repetition rule expression is evaluated when the plan item is completed or terminated. If the expression resolved to *true*, a new instance is created. For example, a human task with a repetition rule expression *${repetitionCounter &lt; 3}*, will create three sequential human tasks.

If the plan item has entry criteria, the behavior is different. The repetition rule is not evaluated on completion or termination, but when a sentry of the plan item is satisfied. If both the sentry is satisfied and the repetition rule evaluates to true, a new instance is created.

Take, for example, the following timer event listener followed by a human task. The sentry has one entry criterion for the *occur* event of the timer event listener. Note that enabling and setting the repetition rule on the task has a visual indicator at the bottom of the rectangle.



If the timer event listener is repeating (for example, *R/PT1H*), the *occur* event will be fired every hour. When the repetition rule expression of the human task evaluates to true, a new human task instance will be created each hour.

Note that Flowable allows to have repeating user and generic event listeners. This is contrary to the CMMN specification (which disallows it), but we believe it is needed for having a more flexible way of using event listeners (for example to model a case where a user might multiple times trigger an action that leads to the creation of tasks).

#### Repetition Rule: Max instance count attribute

There is an extended attribute in the Flowable CMMN model for the repetition rule to take more control about the number of concurrently active plan item instances.
Let’s assume you have a plan item with repetition and an entry sentry with a condition. According to the specification, this would create an endless number of plan item instances as long as the condition is true, which might not be the desired behavior.
With the *maxInstanceCount* attribute on the repetition rule, you can define, if there might be an unlimited number of instances (default according to the spec) or if there should be only one instance at a time or any particular maximum instance count.
If you have repetition and set the *maxInstanceCount* to *unlimited*, you need to control the condition in a way that it only creates as many instances as you want or combine it with an on-part (trigger) to only create a new instances whenever that trigger is fired.

Example with a user task having repetition in combination with an entry sentry and a condition and making sure there is only one instance created at a time:

    ...
    <planItem id="planItem1" name="Task 1" definitionRef="humanTask1">
      <itemControl>
        <repetitionRule flowable:maxInstanceCount="1"></repetitionRule>
      </itemControl>
      <entryCriterion id="entryCriterion1" flowable:sentryRef="sentry1"></entryCriterion>
    </planItem>
    <sentry id="sentry1">
      <ifPart>
        <condition><![CDATA[${vars:getOrDefault('enableTaskA', false)}]]></condition>
      </ifPart>
    </sentry>
    ...

Example with a user task having repetition and a repetition condition to control the number of instances being created (in this example 5 tasks will be created):

    <planItem id="planItem1" name="Task 1" definitionRef="humanTask1">
      <itemControl>
        <repetitionRule flowable:counterVariable="repetitionCounter" flowable:maxInstanceCount="unlimited">
          <condition><![CDATA[${vars:getOrDefault('repetitionCounter', 0) <= 5}]]></condition>
        </repetitionRule>
      </itemControl>
    </planItem>

#### Repetition Rule: Repetition collection variable

Similar to the multi instance type in BPMN, you can also use the repetition rule in CMMN in combination with items in a collection.
There are extended attributes for the repetition rule to make use of a collection of elements to create plan item instances for.

Here is the list of the available, extended attributes to control the repetition rule out of a collection (list) of items:

-   **collectionVariable**, set this attribute to the name of the variable with the collection or an expression resolving to a collection

-   **elementVariable**, if the collection variable is set, you can optionally set an element variable to be used at runtime to hold the element as a local variable of the plan item instance

-   **elementIndexVariable**, if the collection variable is set, you can optionally set an element index variable to be used at runtime to hold the index (0 based) as a local variable of the plan item instance

Depending on how the collection gets used with repetition, the time when it is evaluated might be a bit different.

If there is an on-part (an event triggering the plan item) combined with the collection variable, it gets evaluated whenever that on-part is triggered and if the collection is null or empty at that time, no plan item instances are created.

If there is an on-part in combination with an if-part and a collection based repetition, the behavior is the same, however, the if-part might have deferred event trigger handling, which means the plan item is waiting for the if-part to be satisfied, before the collection is checked for the repetition.
Or in other words: the collection needs to be present at the time the if-part is satisfied and the on-part triggers (or was triggered before), then the collection gets evaluated and according its elements, new plan item instances are being started.

If there is no on-part and no if-part, the collection variable gets evaluated every on every evaluation cycle and as soon as it is not null, it is used to create new plan item instances, even if it is empty.
This is done once and the plan item is then terminated. When using a repetition on collection that way, make sure the collection variable becomes available exactly at the moment you want to evaluate it for repetition, otherwise, combine it with an if-part.

If there is an if-part (but no on-part) in combination with a collection variable for repetition, evaluation waits until the if-part is satisfied and afterwards, the collection variable is evaluated to be non-null.
When the if-part is satisfied and the collection is not null (but might be empty), the collection is used for repetition, then the plan item terminates.

Here is an example of a repetition rule combined with a collection variable:

    <planItem id="planItem1" name="Task (${vars:getOrDefault('item', 'na')} - ${vars:getOrDefault('itemIndex', 'na')})" definitionRef="humanTask1">
        <itemControl>
            <repetitionRule flowable:counterVariable="repetitionCounter" flowable:collectionVariable="myCollection" flowable:elementVariable="item" flowable:elementIndexVariable="itemIndex"></repetitionRule>
        </itemControl>
    </planItem>

The example uses a collection variable named *myCollection* and has an element and even element index variable specified. They both get used for the plan item instance name used in its name expression.
As there is no entry sentry, the collection gets evaluated in each evaluation cycle and as soon as *myCollection* is no longer null, it is used for repetition.

### Item control: Manual Activation Rule

Plan items on the case model can have a *manual activation rule*: an expression that can be used to indicate a certain plan item needs to be *manually activated by an end-user*.
When no expression is set, but the manual activation is enabled (for example, the checkbox is checked in the Flowable Modeler) or the expression is empty, a *true* value is assumed by default.

Stages and all task types can be marked for manual activation. Visually, the task or stage will get a 'play' icon (small triangle pointing to the right) to indicate an end-user will have to manually activate it:



Normally, when a sentry for a plan item is satisfied (or the plan item doesn’t have any sentries) the plan item instance is automatically moved to the *ACTIVE* state. When a manual activation is set though, and it evaluates to true, the plan item instance now becomes *ENABLED* instead of *ACTIVE*. As the name implies, the idea behind this is that end-users manually have to activate the plan item instance. A typical use case is showing a list of buttons of potential plan item instances that can currently be started by the end user.

To start an enabled plan item instance, the *startPlanItemInstance* method of the *CmmnRuntimeService* can be used:

    List<PlanItemInstance> enabledPlanItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
        .caseInstanceId(caseInstance.getId())
        .planItemInstanceStateEnabled()
        .list();

    // ...

    cmmnRuntimeService.startPlanItemInstance(planItemInstance.getId());

Note that the behavior of a task is only executed when the plan item instance moves into the *ACTIVE* state. For example, for a human task, the user task will only be created after calling the *startPlanItemInstance* method.

Plan item instances that are enabled can be moved into the *DISABLED* state:

    cmmnRuntimeService.disablePlanItemInstance(planItemInstance.getId());

Disabled plan item instances can be enabled again:

    cmmnRuntimeService.enablePlanItemInstance(planItemInstance.getId());

Note that with regards to determining stage or case instance termination, the *DISABLED* state is seen as a 'terminal' state. This means that the case instance will terminate when only disabled plan item instances would remain.

### Item control: Required Rule

Plan items on the case model can have a *required rule*: an expression that can be used to indicate a certain plan item is *required by the enclosing stage (or plan model)*. This can be used to indicate which plan items of the case model are required to be executed and which are optional.

When no expression is set, but the required rule is enabled (for example, the checkbox is checked in the Flowable Modeler) or the expression is empty, a *true* value is assumed by default.

The *required rule* works in conjunction with the *autoComplete* attribute on the parent stage:

-   If *autoComplete* resolves to *false* for the stage, which is also the default when nothing is set, **all** child plan item instances must be in an end state (completed, terminated, and so on) for the stage plan item instance to be completed by the engine

-   If *autoComplete* resolves to *true* for the stage, all child plan item instances for **which the required rule evaluates to true** need to be in an end state. If there are also no other active child plan item instances, the stage completes automatically

A *stage plan item instance* has a **completable** property that can be used to see whether or not the conditions for completion are satisfied.
Take, for example, the following simple stage and assume that the sentry for the *required task* evaluates to true and the other one to false. This means that the left plan item instance will be active while the right one will be in the *available* state.



Calling *cmmnRuntimeService.completeStagePlanItemInstance(String stagePlanItemInstanceId)* will not be possible for the stage (an exception will be thrown) as it has one active child plan item instance. When this user task on the left is completed, the *completeStagePlanItemInstance* can now be called, as no child plan item instances are currently active. However, by itself, the stage will not automatically complete as the right user task is in the available state.

If the previous stage is changed to be **autocompletable** (this is visualised by a black rectangle at the bottom of the stage) and the plan item on the left is changed to be required (this is visualised using an exclamation mark), the behavior will be different:



-   If the left plan item instance is active (sentry is true) and the right is not (sentry is false). In this case, when the left user task is completed, the stage instance will auto complete as it has no active child plan item instances and all required plan item instances are in an end state

-   If both the left and right user tasks are active (sentries are true)

    -   When the left user task is completed, the stage will not autocomplete as there is still a child plan item instance active

    -   When the right user task is completed, the stage will not autocomplete as the required left child plan item instance is not in an end state

-   If the left plan item instance is not active and the right is active. In this case, when the right user task is completed the stage will not autocomplete, as the required left user task is not in an end state. It will need to become active and be completed to complete the stage.

Note that the manual activation rule works independently of the required rule. For example, given the following stage:



Here, user task D is required and user task B is manually activated.

-   If D is completed, the stage will automatically complete, as B is not required and it is not active

-   If B would be required too, it would need to be manually started (using *cmmnRuntimeService.startPlanItemInstance(String planItemInstanceId)*) before the stage would automatically complete, even if D would be completed before the manual start of B

### Item control: Completion Neutral Rule

Plan items on the case model can have a *completion neutral rule*: an expression that can be used to indicate a certain plan item is *neutral with regards to the completion of its parent stage (or plan model)*. This can be used to indicate which plan items of the case model are required to be executed and which are optional, as a more flexible alternative in some use cases to using the *required rule* and *autoComplete* .

Note that the *Completion Neutral Rule* is not a CMMN 1.1 Standard, but a Flowable-specific addition.

Following the specification, a stage with a plan item in state **AVAILABLE** does not complete unless its *autoComplete* attribute is set *true* and the plan item is not required. For example, a plan item that has an unsatisfied sentry remains in **AVAILABLE** until the sentry is satisfied. This means that the parent stage would not complete, unless the plan item is marked as *not required* and the stage is set to *autoComplete*. The downside is that once a stage is marked as to autoComplete, all child plan items need to have a configuration for the *required* rule, which is in some use cases tedious and lots of work.

The *Completion Neutral Rule*, contrary to the autoComplete-required mechanism, works from "bottom-up": a plan item can be marked individually to be *neutral wrt the completion of its parent* without having to mark any other plan item.

The *Required Rule* takes precedence when plan items with both rules both evaluate to *true*.

To summarize:

-   a plan item configured to be *"completion neutral"* will allow a stage to complete automatically if it’s in **AVAILABLE** state (e.g. waiting for an entry criterion sentry),meaning that such a plan item is neutral with respect to its parent stage completion evaluation.

-   a stage will remain **ACTIVE** on any of these conditions:

    1.  It has at least one plan item in **ACTIVE** state

    2.  It has at least one plan item with *requiredRule* in **AVAILABLE** or **ENABLE** state

    3.  It is not marked as *autoComplete* and has at least one plan item in **ENABLED** state (irrespective of its *requiredRule*)

    4.  It is not marked as *autoComplete* and has at least one plan item in **AVAILABLE** state that is **not** *completionNeutral*

-   a stage will **COMPLETE** if:

    1.  It contains no plan items or all child plan items are in a *Terminal* or *Semi-terminal* state (CLOSED, COMPLETED, DISABLED, FAILED)

    2.  It is not marked as *autoComplete* and all remaining child plan items are in **AVAILABLE** state and are *completionNeutral* and not *required*

    3.  It is *autoComplete* and all remaining plan items are *not required* in **ENABLED** or **AVAILABLE** state (regardless of its completion neutrality, as required rule gets precedence)

### Item control: Parent Completion Rule

In addition to the *completion neutral rule* (which is going to be deprecated), the *parent completion rule* offers way more flexibility whenever it comes down to evaluating a stage or the case plan model to be completable.
There is the *auto complete* possibility to automatically complete a stage whenever all the required and active work is done, but sometimes, you want a more fine-grained way on how existing plan item instances get treated around the evaluation of its parent being completable.
With the parent completion rule, you can define the behavior of a plan item on its parent completion evaluation.

Here is a list of types currently supported for the parent completion rule:

-   **default**: Use this value if the default behavior is required according the CMMN specification.

-   **ignore**: With this value, the plan item is fully ignored when it is evaluated for its parent completion state. This is particularly useful, if you have plan items (e.g. a case page) to be ignored completely as they don’t have an impact on the case execution or stage completion evaluation.

-   **ignoreIfAvailable**: With this value, the plan item only gets ignored, if it is in *available* state, but will prevent the stage from being completed, if it is *active* or *enabled*.

-   **ignoreIfAvailableOrEnabled**: This value includes the *enabled* (waiting for manual activation) state to be ignored, only an *active* instance will prevent the stage from being completed.

-   **ignoreAfterFirstCompletion**: This value is interesting for instance if you have a user task which has repetition and you want to make sure, it was completed at least once, but afterwards, it must not prevent its parent from being completed, even if it is *active*.

-   **ignoreAfterFirstCompletionIfAvailableOrEnabled**: In contrast to the previous one, use this value, if you want a plan item being ignored after its first completion, if it is in *available* or *enabled* state, but is currently not *active*.

Here is an example on how to use the **parent completion rule** for a plan item. This example uses it in combination with repetition, the required rule and even manual activation.
So it will prevent it’s parent from being completed, if it was not started and completed at least once, but no longer, if it was completed once and is not in *active* state afterwards.

    <planItem id="planItem1" name="Task A" definitionRef="humanTask1">
        <itemControl>
            <extensionElements>
                <flowable:parentCompletionRule type="ignoreAfterFirstCompletionIfAvailableOrEnabled" />
            </extensionElements>
            <repetitionRule></repetitionRule>
            <requiredRule></requiredRule>
            <manualActivationRule></manualActivationRule>
        </itemControl>
    </planItem>

## Sentry evaluation

Sentries play a big role in any case definition as they offer a powerful way of configuring in a declarative way when certain plan item instances activate or when they are automatically stopped.
As such, one of the most important parts of the Flowable CMMN engine core logic is to evaluate the sentries to see what state changes happen in a case instance.

### When are sentries evaluated?

Sentries are evaluated whenever state changes happen in the case instance or new events happen. Concretely this means:

-   When a case instance is started.

-   When a wait state plan item such as a human task is triggered to continue.

-   When variables related to the case instance change (added, updated or deleted).

-   When the state of a plan item instance is changed (e.g. terminated through RuntimeService, a manual plan item instance is started, etc.).

-   When manually triggered through the RuntimeService\#evaluateCriteria method.

The engine will continue to plan new evaluations of all currently active sentries as long as changes keep happening.
For example, suppose the completion of a human task satisfies the exit sentry of another human task. The state change of the second human task will again schedule a new evaluation of all active sentries with this new information. When no changes have happened during the last evaluation, the engine deems the state stable and evaluation is stopped.

### Concepts

Sentries consist of two parts:

-   One or more *onParts* that reference lifecycle events from other plan items

-   Zero or one ifPart with a condition

Take for example the following case definition:



Assume (not shown in the diagram here)

-   The entry sentry on task C listens to the *complete* event from task A and B.

-   The exit sentry listens to the *occur* event of the user event listener *'Stop C'*

-   The entry sentry has a condition expression set to *${var:eq(myVar, 'hello world')}*

In this simple example, the *entry sentry* has two onParts and one ifPart. The *exit sentry* only has onPart.

When the case instance is started, human tasks A and B are created (as they have no entry sentry) and move immediately to state *active*. C is not *active*, but *available* as the sentry has not yet been satisfied. The user event listener *'Stop C'* is also *available* from the start and it can thus be triggered.

When both task A and B have been completed and the variable *myVar* is set to *'hello world'*, the entry sentry is satisfied and fires. The plan item instance behind C is moved to the *active* state and as a side-effect the human task C is created (it can now be queried through the *TaskService* for example).
When *'Stop C'* is triggered (through the *CmmnRuntimeService\#completeUserEventListenerInstance* method, the exit sentry for C is satisfied and C is terminated.

If *'Stop C'* would be triggered before C moves to *active*, its plan item instance would be terminated and the entry sentry won’t be listening anymore to anything.

### Default behavior

When the case instance is started

    CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
        .caseDefinitionKey("myCase")
        .start();

the condition on the entry sentry is immediately evaluated, as a regular evaluation cycle happens on case instance start.

Note that, if an expression for the condition like *${myVar == 'hello world'}* would be used this would not work. The engine would throw a *PropertyNotFound* exception as it doesn’t know the *myVar* variable.

To solve this:

-   pass a variable value for *myVar* on case instance start

-   do a null check in the expression, like *${planItemInstance.getVariable('myVar') != null && planItemInstance.getVariable('myVar') == 'hello world'}*

-   or (and probably easiest), check [expression functions](cmmn/ch03-API.md#expression-functions) to use a function such as *${var:eq(myVar, 'hello world')}* which takes in account the fact the variable might not exist.

**The default evaluation logic has "memory", which means that when a part of a sentry is satisfied the engine will store and "remember" this in subsequent evaluations.**

This means that, from the moment a part (an onPart or ifPart of the sentry) is satisfied, that particular part is not evaluated anymore in next evaluations and it is deemed true.

In the example above, this is needed as task A will typically be completed at another point in time than task B. For example if task A is completed, the part of the sentry on task C that says "i’m listening to the complete event of task A" is now satisfied and this fact is remembered for the future. If now B completes, this is also stored. If now the *myVar* variable gets the right value, the ifPart also fires and the whole sentry fires and task C gets activated. Of course, it could also be that the variable value is satisfied first and the tasks after. The point is that it doesn’t matter as the engine will remember the parts that were satisfied in the past.

This behavior "with memory" is the default behavior of the engine and is covered by setting the *triggerMode* of a sentry to **default**. This is automatically set in the Flowable Modeler when adding a new plan item. When no value has been set (for example when importing a case model from another tool), the *triggerMode* is assumed to be *default*.

### Trigger mode "onEvent"

The default behavior (see previous section) will remember which parts have been satisfied previously. This is the most used and safest approach (and also what is typically expected when reasoning about sentries).

There is an alternative mode of sentry triggering that is called **"onEvent"**. In this mode, the engine will have memory with regards to parts of the sentry and will **not remember** any part that was satisfied in the past. This is sometimes needed in advanced use cases. Take for example the following example:



Here, the case model has a stage with with three substages. All substage are repeating. Substage B and C have an entry sentry for the completion of stage B. Also (not visually shown), both sentries have a condition that depends on a variable.

In advanced use cases, it could be wanted or needed that that the sentry parts (and especially the ifPart containing the condition) are evaluated only *when the lifecycle event of the dependent plan item* happens. In this case, this is the *complete* event of *Stage A*. For these use cases, the *triggerMode* of the sentry can be set to *onEvent*. As the name implies, this means that the sentry evaluation only happens when a referenced event happens and no memory of past things are taken into account.

Concretely, in the example here, the condition of the entry sentries will be evaluated **only** when Stage A completed (and on no other moment). This is very different from the general evaluation rules. In this particular example, it does make managing the variables easier as the conditions are only evaluated on one precise moment and there needs to be no fear of some sentry part being fired due to a variable having a value at a certain point in time. Especially as in the example here all substages are repeating, this would be a lot of work to do. This is a powerful mechanism, but meant for advanced modelers that have an intrinsic knowledge of the case model and the semantics of this triggerMode.

Do note that the engine deems all events to happen simultaneously when it comes to evaluating sentries. Take the following case definition:



Assume that all sentries use the *triggerMode onEvent* setting. If task A is completed, this exits task B. Task C will now exit too. So, even though there are two distinct lifecycle events (A being completed and B being exited) and one might assume that *onEvent* literally means that there are two distinct evaluations happening where the memory of the other part of the exit sentry on task C is forgotten, the engine is smart enough to see that they are part of the same evaluation cycle and task C will be exited too.

Technically spoken: there is *some* memory for the *onEvent* sentry, more specifically for evaluations that happen during the same API call (or transaction, lower-level spoken).

**Important: onEvent is a powerful mechanism and should only be used when the semantics are well understood. It’s possible to create a case model that gets stuck due to not having the correct sentry configuration if the use case is not carefully examined.**

(For example, suppose a sentry has an onPart listening to the completion of a plan item and an ifPart with a condition. If the plan item completes - thus triggering the onPart - but a variable used in the condition is missing for some reason …​ the ifPart would never fire and the case instance might get stuck in an unwanted state).

---

### Docusaurus Docs Cmmn Ch07 Architecture (`docs/docusaurus/docs/cmmn/ch07-architecture.md`)

---
id: ch07-architecture
title: Architecture
---

This chapter gives a short introduction to the internals of the CMMN engine from a high-level point of view. Of course, as the CMMN engine code is open source, the actual implementation details can be found by diving into the source code.

The CMMN engine, as shown in the diagram below, is one of the engines that is part of the Flowable engines eco-system and is designed in a similar way as the other engines. The CMMN engine builds upon CMMN specific services and the shared services: the task, variable, identity and job services, which are independent from the engines. On a lower level the entity- and datamanager layer takes care of the low-level persistence, equivalent to the other engines.



By using the shared services, this also means that for example tasks from both the BPMN and the CMMN engine will end up together and can be queried and managed through the same API. Similarly for the async executor: timers and async jobs use the same logic and even can be managed by a central executor.

The shared services architecture has a second benefit. When the engines are used together, as is often the case, the engines will share resources where possible, database transactions will span calls over multiple engines operations, lookup caches are common and persistency is handled independently from the engines itself.

The CMMN engine is designed with the same principles as the other engines of the Flowable project. The diagram below gives a high-level overview of the different components involved when working with the CMMN Engine:



From a high level point of view:

-   A **CmmnEngine** instance is created from a **CmmnEngineConfiguration**. The configuration instance can be created from a configuration file or programmatically.

-   The *CmmnEngine* gives access the Flowable CMMN API’s in the form of services: **CmmnRepositoryService**, **CmmnRuntimeService**, **CmmnTaskService**, **CmmnHistoryService**, **CmmnManagementService**. The naming of the services and their responsibilities is similar to the other engines.

-   Every API method is transformed into a **Command** instance. This *Command* instance is passed into the **CommandExecutor** which, amongst others, makes it pass a stack of **CommandInterceptors**. These interceptors have various responsibilities, including handling transactions.

-   Eventually, the *Command* typically (unless it’s a pure data modification *Command*) plans a **CmmnOperation** on the **CmmnEngineAgenda**.

-   Operations will be taken from the *CmmnEngineAgenda* until no more operations are left. Typically, an operation will plan new operations as part of its logic.

-   The logic in the operations will call out to lower-level services and/or entity managers.

A big difference between the BPMN and the CMMN engine is that the BPMN engine is generally 'local': the engine looks at the current state, checks what is ahead in the process and continues (of course this is a simplification, there are plenty of operations where this doesn’t apply, but for making a distinction conceptually, it is correct). The CMMN engine works differently: in CMMN, data plays an important role and the change of data can trigger many things in various places in the case definition. For this reason, the **EvaluateCriteriaOperation** is planned and executed often whenever changes happen. The engine does optimize these evaluations when it detects duplicates or useless evaluations.

Core to the working of the CMMN engine is the concept of a **Plan item instance**, a representation of which *plan items* currently are *live* in the case and which state they have. Quite different from BPMN, CMMN defines a strict state life cycle for the plan items. This is represented in the *CmmnRuntimeService* methods, the query API’s and the data fields part of the **PlanItemInstance** object.

The working of the agenda, the operations and how plan item instances are handled can be inspected by setting logging to debug for the agenda package. For example, when using log4j:

    log4j.logger.org.flowable.cmmn.engine.impl.agenda=DEBUG

Which leads to logging like:

    Planned [Init Plan Model] initializing plan model for case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122
    Planned [Change PlanItem state] Task A (id: planItemTaskA), new state: [available] with transition [create]
    Planned [Change PlanItem state] PlanItem Milestone One (id: planItemMileStoneOne), new state: [available] with transition [create]
    Planned [Change PlanItem state] Task B (id: planItemTaskB), new state: [available] with transition [create]
    Planned [Change PlanItem state] PlanItem Milestone Two (id: planItemMileStoneTwo), new state: [available] with transition [create]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'create' having fired for plan item planItemTaskA (Task A)
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'create' having fired for plan item planItemMileStoneOne (PlanItem Milestone One)
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'create' having fired for plan item planItemTaskB (Task B)
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'create' having fired for plan item planItemMileStoneTwo (PlanItem Milestone Two)
    Planned [Activate PlanItem] Task A (planItemTaskA)
    Planned [Change PlanItem state] Task A (id: planItemTaskA), new state: [active] with transition [start]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'start' having fired for plan item planItemTaskA (Task A)
    Planned [Change PlanItem state] Task A (id: planItemTaskA), new state: [completed] with transition [complete]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'complete' having fired for plan item planItemTaskA (Task A)
    Planned [Activate PlanItem] PlanItem Milestone One (planItemMileStoneOne)
    Planned [Change PlanItem state] PlanItem Milestone One (id: planItemMileStoneOne), new state: [active] with transition [start]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'start' having fired for plan item planItemMileStoneOne (PlanItem Milestone One)
    Planned [Change PlanItem state] PlanItem Milestone One (id: planItemMileStoneOne), new state: [completed] with transition [occur]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'occur' having fired for plan item planItemMileStoneOne (PlanItem Milestone One)
    Planned [Activate PlanItem] Task B (planItemTaskB)
    Planned [Change PlanItem state] Task B (id: planItemTaskB), new state: [active] with transition [start]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'start' having fired for plan item planItemTaskB (Task B)
    Planned [Change PlanItem state] Task B (id: planItemTaskB), new state: [completed] with transition [complete]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'complete' having fired for plan item planItemTaskB (Task B)
    Planned [Activate PlanItem] PlanItem Milestone Two (planItemMileStoneTwo)
    Planned [Change PlanItem state] PlanItem Milestone Two (id: planItemMileStoneTwo), new state: [active] with transition [start]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'start' having fired for plan item planItemMileStoneTwo (PlanItem Milestone Two)
    Planned [Change PlanItem state] PlanItem Milestone Two (id: planItemMileStoneTwo), new state: [completed] with transition [occur]
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122 with transition 'occur' having fired for plan item planItemMileStoneTwo (PlanItem Milestone Two)
    Planned [Evaluate Criteria] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122
    No active plan items found for plan model, completing case instance
    Planned [Complete case instance] case instance bfaf0e64-eaf4-11e7-b9d0-acde48001122

---

### Docusaurus Docs Cmmn Ch08 REST (`docs/docusaurus/docs/cmmn/ch08-REST.md`)

---
id: ch08-REST
title: REST API
---

## General Flowable REST principles

### Installation and Authentication

Flowable includes a REST API to the Flowable CMMN engine that can be installed by deploying the flowable-rest.war file to a servlet container like Apache Tomcat. However, it can also be used in another web-application by including the servlet (and/or its mappings) in your application and add all flowable-rest dependencies to the classpath.

By default Flowable REST will connect to an in-memory H2 database. You can change the database settings in the flowable-app.properties file in the *WEB-INF/META-INF/flowable-app* folder. The REST API uses JSON format (<http://www.json.org>) and is built upon the Spring MVC (<http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html>).

All REST-resources require a valid user with the *rest-access-api* privilege to be authenticated by default. If any valid user should be able to call the REST API, the *flowable.rest.app.authentication-mode* can be set to *any-user* (this was the default in older versions of Flowable).

A default user that can access the REST API can be configured by settings the following properties:

    flowable.rest.app.admin.user-id=rest-admin
    flowable.rest.app.admin.password=test
    flowable.rest.app.admin.first-name=Rest
    flowable.rest.app.admin.last-name=Admin

When the REST app boots up, the user is created if it doesn’t exist or fetched otherwise. This user will be given the *access-rest-api* privilege which is needed by default to access the REST API. **Do not forget to change the password of this user afterwards**. If the *flowable.rest.app.admin.user-id* is not set, no users or privileges will be created. So, after the initial setup, removing this property will not remove the user nor the privilege that has been configured before.

Basic HTTP access authentication is used, so you should always include a *Authorization: Basic …​==* HTTP-header when performing requests or include the username and password in the request-url (for example, *<http://username:password@localhost:8080/xyz>*).

**We recommend that you use Basic Authentication in combination with HTTPS.**

### Configuration

The Flowable REST web application uses the Spring Boot Flowable starter for starting the Flowable CMMN engine, defining the basic authentication security using Spring security, and to define the variable converters for specific variable handling.
A small number of properties can be defined by changing the flowable-app.properties file .


### Usage in Tomcat

Due to [default security properties on Tomcat](http://tomcat.apache.org/tomcat-8.0-doc/security-howto.html), **escaped forward slashes (%2F and %5C) are not allowed by default (400-result is returned).** This may have an impact on the deployment resources and their data-URL, as the URL can potentially contain escaped forward slashes.

When issues are experienced with unexpected 400-results, set the following system-property:

*-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW\_ENCODED\_SLASH=true*

It’s best practice to always set the **Accept** and **Content-Type** (in case of posting/putting JSON) headers to **application/json** on the HTTP requests described below.

### Methods and return-codes

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>GET</p></td>
<td><p>Get a single resource or get a collection of resources.</p></td>
</tr>
<tr class="even">
<td><p>POST</p></td>
<td><p>Create a new resource. Also used for executing resource-queries which have a too complex request-structure to fit in the query-URL of a GET-request.</p></td>
</tr>
<tr class="odd">
<td><p>PUT</p></td>
<td><p>Update properties of an existing resource. Also used for invoking actions on an existing resource.</p></td>
</tr>
<tr class="even">
<td><p>DELETE</p></td>
<td><p>Delete an existing resource.</p></td>
</tr>
</tbody>
</table>

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200 - Ok</p></td>
<td><p>The operation was successful and a response has been returned (GET and PUT requests).</p></td>
</tr>
<tr class="even">
<td><p>201 - Created</p></td>
<td><p>The operation was successful and the entity has been created and is returned in the response-body (POST request).</p></td>
</tr>
<tr class="odd">
<td><p>204 - No content</p></td>
<td><p>The operation was successful and entity has been deleted and therefore there is no response-body returned (DELETE request).</p></td>
</tr>
<tr class="even">
<td><p>401 - Unauthorized</p></td>
<td><p>The operation failed. The operation requires an Authentication header to be set. If this was present in the request, the supplied credentials are not valid or the user is not authorized to perform this operation.</p></td>
</tr>
<tr class="odd">
<td><p>403 - Forbidden</p></td>
<td><p>The operation is forbidden and should not be re-attempted. This implies an issue with authorization not authentication, it’s an operation that is not allowed. Example: deleting a task that is part of a running case is not allowed and will never be allowed, regardless of the user or case/task state.</p></td>
</tr>
<tr class="even">
<td><p>404 - Not found</p></td>
<td><p>The operation failed. The requested resource was not found.</p></td>
</tr>
<tr class="odd">
<td><p>405 - Method not allowed</p></td>
<td><p>The operation failed. The method is not allowed for this resource. For example, trying to update (PUT) a deployment-resource will result in a 405 status.</p></td>
</tr>
<tr class="even">
<td><p>409 - Conflict</p></td>
<td><p>The operation failed. The operation causes an update of a resource that has been updated by another operation, which makes the update no longer valid. Can also indicate a resource that is being created in a collection where a resource with that identifier already exists.</p></td>
</tr>
<tr class="odd">
<td><p>415 - Unsupported Media Type</p></td>
<td><p>The operation failed. The request body contains an unsupported media type. Also occurs when the request-body JSON contains an unknown attribute or value that doesn’t have the right format/type to be accepted.</p></td>
</tr>
<tr class="even">
<td><p>500 - Internal server error</p></td>
<td><p>The operation failed. An unexpected exception occurred while executing the operation. The response-body contains details about the error.</p></td>
</tr>
</tbody>
</table>

The media-type of the HTTP-responses is always application/json unless binary content is requested (for example, deployment resource data), the media-type of the content is used.

### Error response body

When an error occurs (both client and server, 4XX and 5XX status-codes) the response body contains an object describing the error that occurred. An example for a 404-status when a task is not found:

    {
      "statusCode" : 404,
      "errorMessage" : "Could not find a task with id '444'."
    }

### Request parameters

#### URL fragments

Parameters that are part of the URL (for example, the deploymentId parameter in http://host/flowable-rest/cmmn-api/cmmn-repository/deployments/{deploymentId})
need to be properly escaped (see [URL-encoding or Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding)) in case the segment contains special characters. Most frameworks have this functionality built in, but it should be taken into account. Especially for segments that can contain forward-slashes (for example, deployment resource), this is required.

#### Rest URL query parameters

Parameters added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/cmmn-api/cmmn-repository/deployments?name=Deployment) can have the following types and are mentioned in the corresponding REST-API documentation:

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. Can contain any valid characters that are allowed in URLs. In the case of a XXXLike parameter, the string should contain the wildcard character % (properly URL-encoded). This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Boolean</p></td>
<td><p>Parameter representing a boolean value. Can be either true or false. All other values other than these will cause a '405 - Bad request' response.</p></td>
</tr>
<tr class="odd">
<td><p>Date</p></td>
<td><p>Parameter representing a date value. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (e.g. 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### JSON body parameters

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. In the case of a XXXLike parameter, the string should contain the wildcard character %. This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value, using a JSON number. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value, using a JSON number. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Date</p></td>
<td><p>Parameter representing a date value, using a JSON text. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (for example, 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### Paging and sorting

Paging and order parameters can be added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/cmmn-api/cmmn-repository/deployments?sort=name).

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>sort</p></td>
<td><p>different per query implementation</p></td>
<td><p>Name of the sort key, for which the default value and the allowed values are different per query implementation.</p></td>
</tr>
<tr class="even">
<td><p>order</p></td>
<td><p>asc</p></td>
<td><p>Sorting order which can be 'asc' or 'desc'.</p></td>
</tr>
<tr class="odd">
<td><p>start</p></td>
<td><p>0</p></td>
<td><p>Parameter to allow for paging of the result. By default the result will start at 0.</p></td>
</tr>
<tr class="even">
<td><p>size</p></td>
<td><p>10</p></td>
<td><p>Parameter to allow for paging of the result. By default the size will be 10.</p></td>
</tr>
</tbody>
</table>

> **Note**
>
> Bear in mind that the start parameter is used as the offset of the query. For example, to get tasks in three pages of three items each (9 items), we would use:
>
>     GET /runtime/tasks?start=0&size=3
>     GET /runtime/tasks?start=3&size=3
>     GET /runtime/tasks?start=6&size=3

#### JSON query variable format

    {
      "name" : "variableName",
      "value" : "variableValue",
      "operation" : "equals",
      "type" : "string"
    }

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>Name of the variable to include in a query. Can be empty in the case where 'equals' is used in some queries to query for resources that have <strong>any variable name</strong> with the given value.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>Yes</p></td>
<td><p>Value of the variable included in the query, should include a correct format for the given type.</p></td>
</tr>
<tr class="odd">
<td><p>operator</p></td>
<td><p>Yes</p></td>
<td><p>Operator to use in query, can have the following values: equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, lessThan, greaterThan, lessThanOrEquals, greaterThanOrEquals and like.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of variable to use. When omitted, the type will be deduced from the value parameter. Any JSON text-values will be considered of type string, JSON booleans of type boolean, JSON numbers of type long or integer depending on the size of the number. We recommended you include an explicit type when in doubt. Types supported out of the box are listed below.</p></td>
</tr>
</tbody>
</table>

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as and converted to a java.lang.String.</p></td>
</tr>
<tr class="even">
<td><p>short</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="odd">
<td><p>integer</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as and converted to a java.lang.Long.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as and converted to a java.lang.Double.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as and converted to a java.lang.Boolean.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as and converted to a java.util.Date. The JSON string will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

#### Variable representation

When working with variables (execute decision), the REST API uses some common principles and JSON-format for both reading and writing. The JSON representation of a variable looks like this:

    {
      "name" : "variableName",
      "value" : "variableValue",
      "valueUrl" : "http://...",
      "type" : "string"
    }

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>Yes</p></td>
<td><p>Name of the variable.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>No</p></td>
<td><p>Value of the variable. When writing a variable and value is omitted, null will be used as value.</p></td>
</tr>
<tr class="odd">
<td><p>valueUrl</p></td>
<td><p>No</p></td>
<td><p>When reading a variable of type binary or serializable, this attribute will point to the URL from where the raw binary data can be fetched.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of the variable. See table below for additional information on types. When writing a variable and this value is omitted, the type will be deduced from the raw JSON-attribute request type and is limited to either string, double, integer and boolean. We advise you to always include a type to make sure no wrong assumption about the type are made.</p></td>
</tr>
</tbody>
</table>

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as a java.lang.String. Raw JSON-text value is used when writing a variable.</p></td>
</tr>
<tr class="even">
<td><p>integer</p></td>
<td><p>Value is treated as a java.lang.Integer. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>short</p></td>
<td><p>Value is treated as a java.lang.Short. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as a java.lang.Long. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as a java.lang.Double. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as a java.lang.Boolean. When writing, JSON boolean value is used for conversion.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as a java.util.Date. When writing, the JSON text will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

It’s possible to support additional variable-types with a custom JSON representation (either simple value or complex/nested JSON object). By extending the initializeVariableConverters() method on org.flowable.cmmn.rest.service.api.CmmnRestResponseFactory, you can add additional org.flowable.rest.variable.RestVariableConverter classes to support converting your POJOs to a format suitable for transferring through REST and converting the REST-value back to your POJO. The actual transformation to JSON is done by Jackson.

## Deployment

**When using Tomcat, please read [Usage in Tomcat](#usage-in-tomcat).**

### List of Deployments

Queries all cmmn deployments and returns matching results.

    GET cmmn-repository/deployments
    
| Parameter | Required | Value | Description |
| ------------- | ------------- |  ------------- | ------------- | 
| name | No | String | Only return deployments with the given name. |
| nameLike | No | String | Only return deployments where the name is like the given string. |
| category | No | String | Only return deployments with the given category. |
| categoryLike | No | String | Only return deployments where the category is like the given string. |
| categoryNotEquals | No | String | Only return deployments where the category does not match the given category. |
| parentDeploymentId | No | String | Only return deployments with the given parent deployment id. |
| parentDeploymentId | No | String | Only return deployments where the parent deployment id is like the given string. |
| tenantId | No | String | Only return deployments with the given tenant identifier. |
| tenantIdLike | No | String | Only return deployments where the tenant identifier is like the given string. |
| withoutTenantId | No | String | Only return deployments that are without a tenant identifier. |
| sort | No | String | Property to sort on, to be used together with order. Possible values: id/name/deployTime/tenantId |

| Response Code | Description |
| ---- | ---- |
| 200 | Indicates the request was successful. |

Example response body:

```
{
    "data": [
        {
            "id": "59eca679-3c6b-11ea-8548-38c986587585",
            "name": "test-case",
            "deploymentTime": "2020-01-21T17:30:35.607+01:00",
            "category": null,
            "parentDeploymentId": null,
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585",
            "tenantId": ""
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "id",
    "order": "asc",
    "size": 1
}
```

### Get a deployment

    GET cmmn-repository/deployments/{deploymentId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|deploymentId|Yes|String|The id of the deployment to get.|

|Response code|Description}
| - | - |
|200|Indicates the deployment was found and returned.|
|404|Indicates the requested deployment was not found.|

*Success response body:*

```
{
    "id": "59eca679-3c6b-11ea-8548-38c986587585",
    "name": "test-case",
    "deploymentTime": "2020-01-21T17:30:35.607+01:00",
    "category": null,
    "parentDeploymentId": null,
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585",
    "tenantId": ""
}
```


### Create a new deployment

    POST cmmn-repository/deployments

*Request body:*

The request body should contain data of type _multipart/form-data_. There should be exactly one file in the request, any additional files will be ignored. The deployment name is the name of the file-field passed in. If multiple resources need to be deployed in a single deployment, compress the resources in a zip and make sure the file-name ends with +.bar+ or +.zip+.

An additional parameter (form-field) can be passed in the request body with name +tenantId+. The value of this field will be used as the id of the tenant this deployment is done in.

|Response code|Description|
| - | - |
|201|Indicates the deployment was created.|
|400|Indicates there was no content present in the request body or the content mime-type is not supported for deployment. The status-description contains additional information.|

*Success response body:*

```
{
    "id": "59eca679-3c6b-11ea-8548-38c986587585",
    "name": "test-case",
    "deploymentTime": "2020-01-21T17:30:35.607+01:00",
    "category": null,
    "parentDeploymentId": null,
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585",
    "tenantId": ""
}
```

### Delete a deployment

    DELETE repository/deployments/{deploymentId}

|Parameter|Required|Value|Description|
|- |- |- |- |
|deploymentId|Yes|String|The id of the deployment to delete.|

|Response code|Description|
|- |- |
|204|Indicates the deployment was found and has been deleted. Response-body is intentionally empty.|
|404|Indicates the requested deployment was not found.|

### List resources in a deployment

    GET cmmn-repository/deployments/{deploymentId}/resources

|Parameter|Required|Value|Description|
|- |- |- |- |
|deploymentId|Yes|String|The id of the deployment to get the resources for.|

|Response code|Description|
|- |- |
|200|Indicates the deployment was found and the resource list has been returned.|
|404|Indicates the requested deployment was not found.|

*Success response body:*

```
[
    {
        "id": "test-case.cmmn.xml",
        "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.cmmn.xml",
        "contentUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resourcedata/test-case.cmmn.xml",
        "mediaType": "text/xml",
        "type": "caseDefinition"
    },
    {
        "id": "test-case.testCase.png",
        "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.testCase.png",
        "contentUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resourcedata/test-case.testCase.png",
        "mediaType": "image/png",
        "type": "resource"
    }
]
```

The contentUrl property in the resulting JSON for a single resource contains the actual URL to use for retrieving the binary resource.


### Get a deployment resource

    GET cmmn-repository/deployments/{deploymentId}/resources/{resourceId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|deploymentId|Yes|String|The id of the deployment the requested resource is part of.|
|resourceId|Yes|String|The id of the resource to get. *Make sure you URL-encode the resourceId in case it contains forward slashes. Eg: use 'diagrams%2Fmy-case.cmmn.xml' instead of 'diagrams/Fmy-case.cmmn.xml'.*|

|Response code|Description |
| - | - |
|200|Indicates both deployment and resource have been found and the resource has been returned.|
|404|Indicates the requested deployment was not found or there is no resource with the given id present in the deployment. The status-description contains additional information.|

*Success response body:*

```
{
    "id": "test-case.cmmn.xml",
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.cmmn.xml",
    "contentUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resourcedata/test-case.cmmn.xml",
    "mediaType": "text/xml",
    "type": "caseDefinition"
}
```

### Get a deployment resource content

    GET cmmn-repository/deployments/{deploymentId}/resourcedata/{resourceId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|deploymentId|Yes|String|The id of the deployment the requested resource is part of.}
|resourceId|Yes|String|The id of the resource to get the data for. *Make sure you URL-encode the resourceId in case it contains forward slashes. Eg: use 'diagrams%2Fmy-case.cmmn.xml' instead of 'diagrams/Fmy-case.cmmn.xml'.*|

|Response code|Description|
| - | - |
|200|Indicates both deployment and resource have been found and the resource data has been returned.|
|404|Indicates the requested deployment was not found or there is no resource with the given id present in the deployment. The status-description contains additional information.|

*Success response body:*

The response body will contain the binary resource-content for the requested resource. The response content-type will be the same as the type returned in the resources 'mimeType' property. Also, a content-disposition header is set, allowing browsers to download the file instead of displaying it.

## Case Definitions


### List of case definitions

    GET cmmn-repository/case-definitions

|Parameter|Required|Value|Description|
| - | - | - | - |
|version|No|integer|Only return case definitions with the given version.
|name|No|String|Only return case definitions with the given name.
|nameLike|No|String|Only return case definitions with a name like the given name.
|key|No|String|Only return case definitions with the given key.
|keyLike|No|String|Only return case definitions with a name like the given key.
|resourceName|No|String|Only return case definitions with the given resource name.
|resourceNameLike|No|String|Only return case definitions with a name like the given resource name.
|category|No|String|Only return case definitions with the given category.
|categoryLike|No|String|Only return case definitions with a category like the given name.
|categoryNotEquals|No|String|Only return case definitions which don't have the given category.
|deploymentId|No|String|Only return case definitions which are part of a deployment with the given id.
|startableByUser|No|String|Only return case definitions which can be started by the given user.
|latest|No|Boolean|Only return the latest case definition versions. Can only be used together with 'key' and 'keyLike' parameters, using any other parameter will result in a 400-response.
|suspended|No|Boolean|If +true+, only returns case definitions which are suspended. If +false+, only active case definitions (which are not suspended) are returned.
|sort|No|'name' (default), 'id', 'key', 'category', 'deploymentId' and 'version'|Property to sort on, to be used together with the 'order'.

|Response code|Description|
| - | - |
|200|Indicates request was successful and the case definitions are returned|
|400|Indicates a parameter was passed in the wrong format or that 'latest' is used with other parameters other than 'key' and 'keyLike'. The status-message contains additional information.|

*Success response body:*

```
{
    "data": [
        {
            "id": "59fd213c-3c6b-11ea-8548-38c986587585",
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
            "key": "testCase",
            "version": 1,
            "name": "Test Case",
            "description": null,
            "tenantId": "",
            "deploymentId": "59eca679-3c6b-11ea-8548-38c986587585",
            "deploymentUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585",
            "resource": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.cmmn.xml",
            "diagramResource": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.testCase.png",
            "category": "http://flowable.org/cmmn",
            "graphicalNotationDefined": true,
            "startFormDefined": false
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "name",
    "order": "asc",
    "size": 1
}
```


* `graphicalNotationDefined`: Indicates the case definition contains graphical information (BPMN DI).
* `resource`: Contains the actual deployed CMMN 1.1 xml.
* `diagramResource`: Contains a graphical representation of the case definition, null when no diagram is available.


### Get a case definition

    GET cmmn-repository/case-definitions/{caseDefinitionId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition to get.|

|Response code|Description|
| - | - |
|200|Indicates the case definition was found and returned.|
|404|Indicates the requested case definition was not found|

*Success response body:*

```
{
    "id": "59fd213c-3c6b-11ea-8548-38c986587585",
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
    "key": "testCase",
    "version": 1,
    "name": "Test Case",
    "description": null,
    "tenantId": "",
    "deploymentId": "59eca679-3c6b-11ea-8548-38c986587585",
    "deploymentUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585",
    "resource": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.cmmn.xml",
    "diagramResource": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/deployments/59eca679-3c6b-11ea-8548-38c986587585/resources/test-case.testCase.png",
    "category": "http://flowable.org/cmmn",
    "graphicalNotationDefined": true,
    "startFormDefined": false
}
```

* `graphicalNotationDefined`: Indicates the case definition contains graphical information (BPMN DI).
* `resource`: Contains the actual deployed BPMN 2.0 xml.
* `diagramResource`: Contains a graphical representation of the case, null when no diagram is available.


### Update category for a case definition

    PUT cmmn-repository/case-definitions/{caseDefinitionId}

*Body JSON:*

```
{
  "category" : "updatedcategory"
}
```


|Response code|Description|
| - | - |
|200|Indicates the case was category was altered.|
|400|Indicates no category was defined in the request body.|
|404|Indicates the requested case definition was not found.|

### Get a case definition resource content

    GET cmmn-repository/case-definitions/{caseDefinitionId}/resourcedata

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition to get the resource data for.|

*Response:*

Exactly the same response codes/boy as +GET cmmn-repository/deployment/{deploymentId}/resourcedata/{resourceId}+.


### Get a case definition BPMN model

    GET cmmn-repository/case-definitions/{caseDefinitionId}/model

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition to get the model for.|

|Response code|Description|
| - | - |
|200|Indicates the case definition was found and the model is returned.|
|404|Indicates the requested case definition was not found.|

*Response body:*
The response body is a JSON representation of the +org.flowable.cmmn.model.CmmnModel+ and contains the full case definition model.

### Get all candidate starters for a case-definition

    GET repository/case-definitions/{caseDefinitionId}/identitylinks

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition to get the identity links for.|

|Response code|Description|
| - | - |
|200|Indicates the case definition was found and the requested identity links are returned.|
|404|Indicates the requested case definition was not found.|

*Success response body:*

```
[
    {
        "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585/identitylinks/groups/flowableUser",
        "user": null,
        "group": "flowableUser",
        "type": "candidate"
    }
]
```


### Add a candidate starter to a case definition

    POST cmmn-repository/case-definitions/{caseDefinitionId}/identitylinks

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition.|

*Request body (user):*

```
{
  "user" : "kermit"
}
```

*Request body (group):*

```
{
  "groupId" : "sales"
}
```

|Response code|Description|
| - | - |
|201|Indicates the case definition was found and the identity link was created.|
|404|Indicates the requested case definition was not found.|

*Success response body:*

### Delete a candidate starter from a case definition

    DELETE cmmn-repository/case-definitions/{caseDefinitionId}/identitylinks/{family}/{identityId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition.|
|family|Yes|String|Either +users+ or +groups+, depending on the type of identity link.|
|identityId|Yes|String|Either the userId or groupId of the identity to remove as candidate starter.|

|Response code|Description|
|- | - |
|204|Indicates the case definition was found and the identity link was removed. The response body is intentionally empty.|
|404|Indicates the requested case definition was not found or the case definition doesn't have an identity-link that matches the url.|

### Get a candidate starter from a case definition

    GET cmmn-repository/case-definitions/{caseDefinitionId}/identitylinks/{family}/{identityId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseDefinitionId|Yes|String|The id of the case definition.|
|family|Yes|String|Either +users+ or +groups+, depending on the type of identity link.|
|identityId|Yes|String|Either the userId or groupId of the identity to get as candidate starter.|

|Response code|Description|
| - | - |
|200|Indicates the case definition was found and the identity link was returned.|
|404|Indicates the requested case definition was not found or the case definition doesn't have an identity-link that matches the url.|


## Case Instances

### Get a case instance

    GET cmmn-runtime/case-instances/{caseInstanceId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseInstanceId|Yes|String|The id of the case instance to get.|

|Response code|Description|
| - | - |
|200|Indicates the case instance was found and returned.|
|404|Indicates the requested case instance was not found.|

*Success response body:*

```
{
    "data": [
        {
            "id": "095fd94e-3c78-11ea-8548-38c986587585",
            "name": null,
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585",
            "businessKey": null,
            "startTime": "2020-01-21T19:01:23.923+01:00",
            "startUserId": "rest-admin",
            "state": "active",
            "ended": false,
            "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionName": "Test Case",
            "caseDefinitionDescription": null,
            "parentId": null,
            "callbackId": null,
            "callbackType": null,
            "referenceId": null,
            "referenceType": null,
            "variables": [],
            "tenantId": "",
            "completed": false
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "id",
    "order": "asc",
    "size": 1
}
```

### Delete a case instance

    DELETE cmmn-runtime/case-instances/{caseInstanceId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|caseInstanceId|Yes|String|The id of the case instance to delete.|

|Response code|Description|
| - | - |
|204|Indicates the case instance was found and deleted. Response body is left empty intentionally.|
|404|Indicates the requested case instance was not found.|

### Start a case instance

    POST cmmn-runtime/case-instances

*Request body (start by case definition id):*

```
{
      "caseDefinitionId":"59fd213c-3c6b-11ea-8548-38c986587585",
      "variables": [
         {
           "name":"myVar",
           "value":"This is a variable"
         }
      ]
   }
```

*Request body (start by case definition key):*

```
{
   "caseDefinitionKey":"testCase",
   "businessKey":"myBusinessKey",
   "tenantId": "tenant1",
   "variables": [
      {
        "name":"myVar",
        "value":"This is a variable"
      }
   ]
}
```

Note that also a _transientVariables_ property is accepted as part of this json, that follows the same structure as the _variables_ property.

The _returnVariables_ property can be used to get the existing variables in the case instance context back in the response. By default the variables are not returned.

Only one of +caseDefinitionId+ or +caseDefinitionKey+  can be used in the request body. Parameters +businessKey+, +variables+ and +tenantId+ are optional. If +tenantId+ is omitted, the default tenant will be used.


|Response code|Description|
| - | - |
|201|Indicates the case instance was created.|
|400|Indicates either the case-definition was not found (based on id or key) or an invalid variable has been passed. Status description contains additional information about the error.}

*Success response body:*

```
{
    "id": "095fd94e-3c78-11ea-8548-38c986587585",
    "name": null,
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585",
    "businessKey": null,
    "startTime": "2020-01-21T19:01:23.923+01:00",
    "startUserId": "rest-admin",
    "state": "active",
    "ended": false,
    "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
    "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
    "caseDefinitionName": "Test Case",
    "caseDefinitionDescription": null,
    "parentId": null,
    "callbackId": null,
    "callbackType": null,
    "referenceId": null,
    "referenceType": null,
    "variables": [
        {
            "name": "myVar",
            "type": "string",
            "value": "This is a variable",
            "scope": "local"
        },
        {
            "name": "initiator",
            "type": "string",
            "value": "rest-admin",
            "scope": "local"
        }
    ],
    "tenantId": "",
    "completed": false
}
```

### List of case instances

    GET cmmn-runtime/case-instances

|Parameter|Required|Value|Description
| - | - | - | - |
|id|No|String|Only return case instance with the given id.|
|caseDefinitionKey|No|String|Only return case instances with the given case definition key.|
|caseDefinitionId|No|String|Only return case instances with the given case definition id.|
|businessKey|No|String|Only return case instances with the given businessKey.|
|involvedUser|No|String|Only return case instances in which the given user is involved.|
|includeCaseVariables|No|Boolean|Indication to include case variables in the result.
|tenantId|No|String|Only return case instances with the given tenantId.
|tenantIdLike|No|String|Only return case instances with a tenantId like the given value.
|withoutTenantId|No|Boolean|If +true+, only returns case instances without a tenantId set. If +false+, the +withoutTenantId+ parameter is ignored.
|sort|No|String|Sort field, should be either one of +id+ (default), +caseDefinitionId+, +tenantId+ or +caseDefinitionKey+.

|Response code|Description|
| - | - |
|200|Indicates request was successful and the case-instances are returned|
|400|Indicates a parameter was passed in the wrong format . The status-message contains additional information.|

*Success response body:*

```
{
    "data": [
        {
            "id": "095fd94e-3c78-11ea-8548-38c986587585",
            "name": null,
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585",
            "businessKey": null,
            "startTime": "2020-01-21T19:01:23.923+01:00",
            "startUserId": "rest-admin",
            "state": "active",
            "ended": false,
            "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionName": "Test Case",
            "caseDefinitionDescription": null,
            "parentId": null,
            "callbackId": null,
            "callbackType": null,
            "referenceId": null,
            "referenceType": null,
            "variables": [],
            "tenantId": "",
            "completed": false
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "id",
    "order": "asc",
    "size": 1
}
```

### Query case instances

Alternative to the GET method, which takes a body with query parameters

    POST query/case-instances


*Request body:*

```
{
  "caseDefinitionKey":"myCase",
  "variables":
  [
    {
        "name" : "myVariable",
        "value" : 1234,
        "operation" : "equals",
        "type" : "long"
    }
  ]
}
```

|Response code|Description|
| - | - |
|200|Indicates request was successful and the case-instances are returned|
|400|Indicates a parameter was passed in the wrong format . The status-message contains additional information.|


### Get diagram for a case instance

    GET cmmn-runtime/case-instances/{caseInstanceId}/diagram

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to get the diagram for.|

|Response code|Description|
| - | - |
|200|Indicates the case instance was found and the diagram was returned.|
|400|Indicates the requested case instance was not found but the case doesn't contain any graphical information (CMMN:DI) and no diagram can be created.}
|404|Indicates the requested case instance was not found.|

### Get involved people for case instance

    GET cmmn-runtime/case-instances/{caseInstanceId}/identitylinks

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to the links for.|

|Response code|Description|
| - | - |
|200|Indicates the case instance was found and links are returned.|
|404|Indicates the requested case instance was not found.|


*Success response body:*

```
[
    {
        "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585/identitylinks/users/rest-admin/starter",
        "user": "rest-admin",
        "group": null,
        "type": "starter"
    },
    {
        "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585/identitylinks/users/rest-admin/participant",
        "user": "rest-admin",
        "group": null,
        "type": "participant"
    }
]
```


### Add an involved user to a case instance

    POST cmmn-runtime/case-instances/{caseInstanceId}/identitylinks

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to the links for.|

*Request body:*

```
{
  "userId":"kermit",
  "type":"participant"
}
```


Both +userId+ and +type+ are required.

|Response code|Description|
| - | - |
|201|Indicates the case instance was found and the link is created.|
|400|Indicates the requested body did not contain a userId or a type.|
|404|Indicates the requested case instance was not found.|

### Remove an involved user to from case instance

    DELETE cmmn-runtime/case-instances/{caseInstanceId}/identitylinks/users/{userId}/{type}


|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance.|
|userId|Yes|String|The id of the user to delete link for.|
|type|Yes|String|Type of link to delete.|

|Response code|Description|
| - | - |
|204|Indicates the case instance was found and the link has been deleted. Response body is left empty intentionally.|
|404|Indicates the requested case instance was not found or the link to delete doesn't exist. The response status contains additional information about the error.|

### List of variables for a case instance

    GET cmmn-runtime/case-instances/{caseInstanceId}/variables

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to the variables for.|

|Response code|Description|
| - | - |
|200|Indicates the case instance was found and variables are returned.|
|404|Indicates the requested case instance was not found.|


*Success response body:*

```
| - | - | - | - | 
```


In case the variable is a binary variable or serializable, the +valueUrl+ points to an URL to fetch the raw value. If it's a plain variable, the value is present in the response.


### Get a variable for a case instance

    GET cmmn-runtime/case-instances/{caseInstanceId}/variables/{variableName}

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to the variables for.|
|variableName|Yes|String|Name of the variable to get.|

|Response code|Description|
| - | - |
|200|Indicates both the case instance and variable were found and variable is returned.|
|400|Indicates the request body is incomplete or contains illegal values. The status description contains additional information about the error.|
|404|Indicates the requested case instance was not found or the case instance does not have a variable with the given name. Status description contains additional information about the error.|

*Success response body:*

```
{
    "name": "myVar",
    "type": "string",
    "value": "This is a variable",
    "scope": null
}
```


In case the variable is a binary variable or serializable, the +valueUrl+ points to an URL to fetch the raw value. If it's a plain variable, the value is present in the response.  Note that only +local+ scoped variables are returned, as there is no +global+ scope for case-instance variables.


### Create (or update) variables on a case instance

    POST cmmn-runtime/case-instances/{caseInstanceId}/variables

    PUT cmmn-runtime/case-instances/{caseInstanceId}/variables


When using +POST+, all variables that are passed are created. In case one of the variables already exists on the case instance, the request results in an error (409 - CONFLICT). When +PUT+ is used, nonexistent variables are created on the case-instance and existing ones are overridden without any error.

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to the variables for.|


*Request body:*

```
[
   {
      "name":"intProcVar",
      "type":"integer",
      "value":123
   },

   ...
]
```


Any number of variables can be passed into the request body array.

|Response code|Description|
| - | - |
|201|Indicates the case instance was found and variable is created.|
|400|Indicates the request body is incomplete or contains illegal values. The status description contains additional information about the error.|
|404|Indicates the requested case instance was not found.|
|409|Indicates the case instance was found but already contains a variable with the given name (only thrown when POST method is used). Use the update-method instead.|

### Update a single variable on a case instance

    PUT cmmn-runtime/case-instances/{caseInstanceId}/variables/{variableName}

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to the variables for.|
|variableName|Yes|String|Name of the variable to get.|

```
 {
    "name":"intProcVar"
    "type":"integer"
    "value":123
 }
```


|Response code|Description|
| - | - |
|200|Indicates both the case instance and variable were found and variable is updated.|
|404|Indicates the requested case instance was not found or the case instance does not have a variable with the given name. Status description contains additional information about the error.|


In case the variable is a binary variable or serializable, the +valueUrl+ points to an URL to fetch the raw value. If it's a plain variable, the value is present in the response.

### Create a new binary variable on a case-instance

    POST runtime/case-instances/{caseInstanceId}/variables


|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to create the new variable for.|

*Request body:*

The request should be of type +multipart/form-data+. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

* `name`: Required name of the variable.
* `type`: Type of variable that is created. If omitted, +binary+ is assumed and the binary data in the request will be stored as an array of bytes.


*Success response body:*

```
{
    "name": "test",
    "type": "binary",
    "value": null,
    "valueUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585/variables/test/data",
    "scope": "local"
}
```

|Response code|Description|
| - | - |
|201|Indicates the variable was created and the result is returned.|
|400|Indicates the name of the variable to create was missing. Status message provides additional information.|
|404|Indicates the requested case instance was not found.|
|409|Indicates the case instance already has a variable with the given name. Use the PUT method to update the task variable instead.|
|415|Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.|

### Update an existing binary variable on a case-instance

    PUT runtime/case-instances/{caseInstanceId}/variables

|Parameter|Required|Value|Description|
| - | - | - | - | 
|caseInstanceId|Yes|String|The id of the case instance to create the new variable for.|

*Request body:*
The request should be of type +multipart/form-data+. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

* `name`: Required name of the variable.
* `type`: Type of variable that is created. If omitted, +binary+ is assumed and the binary data in the request will be stored as an array of bytes.


|Response code|Description|
| - | - |
|200|Indicates the variable was updated and the result is returned.|
|400|Indicates the name of the variable to update was missing. Status message provides additional information.|
|404|Indicates the requested case instance was not found or the case instance does not have a variable with the given name.|
|415|Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.|

### Get a stage overview

    GET /cmmn-runtime/{caseInstanceId}/stage-overview
    
|Parameter|Required|Value|Description|
| - | - | - | - |
|caseInstanceId|No|String|The case instance id for which the stage overview is retrieved.|    

*Success response body* {

```
[
    {
        "id": "stage1",
        "name": "First Stage",
        "current": true
        "ended": false,
        "endTime": null,
    },
    {
        "id": "stage2",
        "name": "Second stage",
        "current": false
        "ended": false,
        "endTime": null,
    }
]
```

## Plan Item instances

### List of plan item instances

    GET cmmn-runtime/plan-item-instances

|Parameter|Required|Value|Description|
| - | - | - | - |
|id|No|String|Only return plan item instances with the given id.|
|caseDefinitionId|No|String|Only return plan item instances with the given case definition id.|
|caseInstanceId|No|String|Only return plan item instances with the given case instance id.|
|stageInstanceId|No|String|Only return plan item instances with the given stage instance id (which is a plan item instance itself).|
|planItemDefinitionId|No|String|Only return plan item instances with the given plan item definition id.|
|planItemDefinitionType|No|String|Only return plan item instances with the given plan item definition type (e.g. stage, milestone, etc.).|
|planItemDefinitionTypes|No|String|Only return plan item instances which have any of the passed types. The types are passed as a comma-separated list.|
|state|No|String|Only return plan item instances which are in the given state.|
|name|No|String|Only return plan item instances with the given name.|
|elementId|No|String|Only return plan item instances with the given element id (as given in the CMMN model).|
|referenceId|No|String|Only return plan item instances with the given reference id (e.g. when the plan item is a process task).|
|referenceType|No|Date|Only return plan item instances with the given reference type.|
|createdBefore|No|Date|Only return plan item instances which were started before the given date.|
|createdAfter|No|String|Only return plan item instances which were started after the given date.|
|starUserId|No|String|Only return plan item instances which were started by the given user.|
|tenantId|No|String|Only return plan item instances with the given tenant id.|
|withoutTenantId|No|String|Only return plan item instances which have no tenant id.|
|sort|No|'name' and 'createTime'|Property to sort on, to be used together with the 'order'.|

|Response code|Description|
| - | - |
|200|Indicates request was successful and the plan item instances are returned.|
|400|Indicates a parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Get a single plan item instance

    GET cmmn-runtime/plan-item-instances/{planItemInstanceId}
    
|Parameter|Required|Value|Description|
| - | - | - | - | 
|planItemInstanceId|Yes|String|The id of the plan item instance.|

|Response code|Description|
| - | - |
|200|Indicates request was successful and the plan item instance is returned.|
|404|Indicates the plan item instance was not found.|

*Success response body:*

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Execute an action on a plan item instance

    PUT cmmn-runtime/plan-item-instances/{planItemInstanceId}
    
Using a JSON body like

```
{
    "action": "start"
}
```    

Possible actions:

|Action|Description|
| - | - |
|start|Starts a plan item (which needs to be in the enabled state).|
|trigger|Triggers a plan item (which is waiting for a trigger).|
|enable|Enables a plan item (which is currently disabled).|
|disable|Triggers a plan item (which is currently enabled).|
|evaluateCriteria|Evaluates the plan item instances sentries (and anything that would have a consequence of doing that).|


## Tasks

### List of tasks

    GET cmmn-runtime/tasks

|Parameter|Required|Value|Description
| - | - | - | - |
|name|No|String|Only return tasks with the given name.
|nameLike|No|String|Only return tasks with a name like the given name.
|description|No|String|Only return tasks with the given description.
|priority|No|Integer|Only return tasks with the given priority.
|minimumPriority|No|Integer|Only return tasks with a priority greater than the given value.
|maximumPriority|No|Integer|Only return tasks with a priority lower than the given value.
|assignee|No|String|Only return tasks assigned to the given user.
|assigneeLike|No|String|Only return tasks assigned with an assignee like the given value.
|owner|No|String|Only return tasks owned by the given user.
|ownerLike|No|String|Only return tasks assigned with an owner like the given value.
|unassigned|No|Boolean|Only return tasks that are not assigned to anyone. If +false+ is passed, the value is ignored.
|delegationState|No|String|Only return tasks that have the given delegation state. Possible values are +pending+ and +resolved+.
|candidateUser|No|String|Only return tasks that can be claimed by the given user. This includes both tasks where the user is an explicit candidate for and task that are claimable by a group that the user is a member of.
|candidateGroup|No|String|Only return tasks that can be claimed by a user in the given group.
|candidateGroups|No|String|Only return tasks that can be claimed by a user in the given groups. Values split by comma.
|involvedUser|No|String|Only return tasks in which the given user is involved.
|taskDefinitionKey|No|String|Only return tasks with the given task definition id.
|taskDefinitionKeyLike|No|String|Only return tasks with a given task definition id like the given value.
|caseInstanceId|No|String|Only return tasks which are part of the case instance with the given id.
|caseDefinitionId|No|String|Only return tasks which are part of the case definition with the given id.
|createdOn|No|ISO Date|Only return tasks which are created on the given date.
|createdBefore|No|ISO Date|Only return tasks which are created before the given date.
|createdAfter|No|ISO Date|Only return tasks which are created after the given date.
|dueOn|No|ISO Date|Only return tasks which are due on the given date.
|dueBefore|No|ISO Date|Only return tasks which are due before the given date.
|dueAfter|No|ISO Date|Only return tasks which are due after the given date.
|withoutDueDate|No|boolean|Only return tasks which don't have a due date. The property is ignored if the value is +false+.
|excludeSubTasks|No|Boolean|Only return tasks that are not a subtask of another task.
|active|No|Boolean|If +true+, only return tasks that are not suspended (either part of a process that is not suspended or not part of a process at all). If false, only tasks that are part of suspended process instances are returned.
|includeTaskLocalVariables|No|Boolean|Indication to include task local variables in the result.
|tenantId|No|String|Only return tasks with the given tenantId.
|tenantIdLike|No|String|Only return tasks with a tenantId like the given value.
|withoutTenantId|No|Boolean|If +true+, only returns tasks without a tenantId set. If +false+, the +withoutTenantId+ parameter is ignored.
|candidateOrAssigned|No|String|Select tasks that has been claimed or assigned to user or waiting to claim by user (candidate user or groups).
|category|No|string|Select tasks with the given category. Note that this is the task category, not the category of the case definition.


|Response code|Description|
| - | -|
|200|Indicates request was successful and the tasks are returned|
|400|Indicates a parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

```
{
    "data": [
        {
            "id": "09688be5-3c78-11ea-8548-38c986587585",
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/tasks/09688be5-3c78-11ea-8548-38c986587585",
            "owner": null,
            "assignee": "rest-admin",
            "delegationState": null,
            "name": "Human task",
            "description": null,
            "createTime": "2020-01-21T19:01:23.975+01:00",
            "dueDate": null,
            "priority": 50,
            "suspended": false,
            "claimTime": null,
            "taskDefinitionKey": "humanTask1",
            "tenantId": "",
            "category": null,
            "formKey": null,
            "parentTaskId": null,
            "parentTaskUrl": null,
            "caseInstanceId": "095fd94e-3c78-11ea-8548-38c986587585",
            "caseInstanceUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585",
            "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
            "variables": []
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "id",
    "order": "asc",
    "size": 1
}
```

### Get a task

    GET cmmn-runtime/tasks/{taskId}

|Parameter|Required|Value|Description|
| - | - | - | - |
|taskId|Yes|String|The id of the task to get.

|Response code|Description|
|- | - |
|200|Indicates the task was found and returned.|
|404|Indicates the requested task was not found.|

*Success response body:*

```
{
    "id": "09688be5-3c78-11ea-8548-38c986587585",
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/tasks/09688be5-3c78-11ea-8548-38c986587585",
    "owner": null,
    "assignee": "rest-admin",
    "delegationState": null,
    "name": "Human task",
    "description": null,
    "createTime": "2020-01-21T19:01:23.975+01:00",
    "dueDate": null,
    "priority": 50,
    "suspended": false,
    "claimTime": null,
    "taskDefinitionKey": "humanTask1",
    "tenantId": "",
    "category": null,
    "formKey": null,
    "parentTaskId": null,
    "parentTaskUrl": null,
    "caseInstanceId": "095fd94e-3c78-11ea-8548-38c986587585",
    "caseInstanceUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/case-instances/095fd94e-3c78-11ea-8548-38c986587585",
    "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
    "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
    "variables": []
}
```

### Update a task

    PUT cmmn-runtime/tasks/{taskId}

*Body JSON:*

```
{
  "assignee" : "assignee",
  "delegationState" : "resolved",
  "description" : "New task description",
  "dueDate" : "2020-04-17T13:06:02.438+02:00",
  "name" : "New task name",
  "owner" : "owner",
  "parentTaskId" : "3",
  "priority" : 20
}
```

All request values are optional. For example, you can only include the 'assignee' attribute in the request body JSON-object, only updating the assignee of the task, leaving all other fields unaffected. When an attribute is explicitly included and is set to null, the task-value will be updated to null. Example: +{"dueDate" : null}+ will clear the duedate of the task).

Following parameters are available to update:

|Parameter|Type|
|-|-|
|name|String|
|description|String|
|dueDate|Date|
|assignee|String|
|owner|String|
|parentTaskId|String|
|priority|integer|
|category|String|
|formKey|String|
|delegationState|String|
|tenantId|String|


|Response code|Description
|-|-|
|200|Indicates the task was updated.
|404|Indicates the requested task was not found.
|409|Indicates the requested task was updated simultaneously.

### Task actions

    POST cmmn-runtime/tasks/{taskId}

*Complete a task - Body JSON:*

```
{
  "action" : "complete",
  "variables" : []
}
```

|Parameter|Type|Description|
|-|-|-|
|action|String|Can be complete, claim, delegate or resolve.|
|assignee|String|The assignee of the task|
|outcome|String|Used when completing the task to designate the outcome of the task.|
|variables|String|Variables to be set.|
|transientVariables|String|Transient variables to set|

*Claim a task - Body JSON:*

```
{
  "action" : "claim",
  "assignee" : "userWhoClaims"
}
```

Claims the task by the given assignee. If the assignee is +null+, the task is assigned to no-one, claimable again.


|Response code|Description|
|-|-|
|200|Indicates the action was executed.|
|400|When the body contains an invalid value or when the assignee is missing when the action requires it.|
|404|Indicates the requested task was not found.|
|409|Indicates the action cannot be performed due to a conflict. Either the task was updates simultaneously or the task was claimed by another user, in case of the '`claim`' action.|

### Delete a task

    DELETE cmmn-runtime/tasks/{taskId}?cascadeHistory={cascadeHistory}&deleteReason={deleteReason}


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to delete.|
|cascadeHistory|False|Boolean|Whether or not to delete the HistoricTask instance when deleting the task (if applicable). If not provided, this value defaults to false.|
|deleteReason|False|String|Reason why the task is deleted. This value is ignored when +cascadeHistory+ is true.|

|Response code|Description|
|-|-|
|204|Indicates the task was found and has been deleted. Response-body is intentionally empty.|
|403|Indicates the requested task cannot be deleted because it's part of a case instance.|
|404|Indicates the requested task was not found.|

### Get all variables for a task

    GET cmmn-runtime/tasks/{taskId}/variables?scope={scope}


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to get variables for.|
|scope|False|String|Scope of variables to be returned. When '`local`', only task-local variables are returned. When '`global`', only variables from the task's parent execution-hierarchy are returned. When the parameter is omitted, both local and global variables are returned.|

|Response code|Description|
|-|-|
|200|Indicates the task was found and the requested variables are returned.|
|404|Indicates the requested task was not found.|

*Success response body:*

```
[
    {
        "name": "myVar",
        "type": "string",
        "value": "This is a variable",
        "scope": "global"
    },
    {
        "name": "test",
        "type": "binary",
        "value": null,
        "valueUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/tasks/09688be5-3c78-11ea-8548-38c986587585/variables/test/data",
        "scope": "global"
    },
    {
        "name": "initiator",
        "type": "string",
        "value": "rest-admin",
        "scope": "global"
    }
]
```

### Get a variable from a task

    GET cmmn-runtime/tasks/{taskId}/variables/{variableName}?scope={scope}


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to get a variable for.|
|variableName|Yes|String|The name of the variable to get.|
|scope|False|String|Scope of variable to be returned. When '`local`', only task-local variable value is returned. When '`global`', only variable value from the task's parent execution-hierarchy are returned. When the parameter is omitted, a local variable will be returned if it exists, otherwise a global variable.|

|Response code|Description|
|-|-|
|200|Indicates the task was found and the requested variables are returned.|
|404|Indicates the requested task was not found or the task doesn't have a variable with the given name (in the given scope). Status message provides additional information.|


*Success response body:*

```
{
    "name": "myVar",
    "type": "string",
    "value": "This is a variable",
    "scope": "global"
}
```


### Get the binary data for a variable

    GET cmmn-runtime/tasks/{taskId}/variables/{variableName}/data?scope={scope}


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to get a variable data for.|
|variableName|Yes|String|The name of the variable to get data for. Only variables of type +binary+ and +serializable+ can be used. If any other type of variable is used, a +404+ is returned.|
|scope|False|String|Scope of variable to be returned. When '`local`', only task-local variable value is returned. When '`global`', only variable value from the task's parent execution-hierarchy are returned. When the parameter is omitted, a local variable will be returned if it exists, otherwise a global variable.|

|Response code|Description|
|-|-|
|200|Indicates the task was found and the requested variables are returned.|
|404|Indicates the requested task was not found or the task doesn't have a variable with the given name (in the given scope) or the variable doesn't have a binary stream available. Status message provides additional information.|

*Success response body:*

The response body contains the binary value of the variable. When the variable is of type +binary+, the content-type of the response is set to +application/octet-stream+, regardless of the content of the variable or the request accept-type header. In case of +serializable+, +application/x-java-serialized-object+ is used as content-type.


### Create new variables on a task

    POST cmmn-runtime/tasks/{taskId}/variables

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to create the new variable for.|


*Request body for creating simple (non-binary) variables:*

```
[
  {
    "name" : "myTaskVariable",
    "scope" : "local",
    "type" : "string",
    "value" : "Hello World"
  },
  {
    ...
  }
]
```


The request body should be an array containing one or more JSON-objects representing the variables that should be created.

* `name`: Required name of the variable
* `scope`: Scope of variable that is created. If omitted, +local+ is assumed.
* `type`: Type of variable that is created. If omitted, reverts to raw JSON-value type (string, boolean, integer or double).
* `value`: Variable value.

|Response code|Description|
|-|-|
|201|Indicates the variables were created and the result is returned.|
|400|Indicates the name of a variable to create was missing or that an attempt is done to create a variable on a standalone task (without a process associated) with scope +global+ or an empty array of variables was included in the request or request did not contain an array of variables. Status message provides additional information.|
|404|Indicates the requested task was not found.|
|409|Indicates the task already has a variable with the given name. Use the PUT method to update the task variable instead.|

### Create a new binary variable on a task

    POST cmmn-runtime/tasks/{taskId}/variables


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to create the new variable for.|


*Request body:*

The request should be of type +multipart/form-data+. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

* `name`: Required name of the variable.
* `scope`: Scope of variable that is created. If omitted, +local+ is assumed.
* `type`: Type of variable that is created. If omitted, +binary+ is assumed and the binary data in the request will be stored as an array of bytes.

|Response code|Description|
|-|-|
|201|Indicates the variable was created and the result is returned.|
|400|Indicates the name of the variable to create was missing or that an attempt is done to create a variable on a standalone task (without a process associated) with scope +global+. Status message provides additional information.|
|404|Indicates the requested task was not found.|
|409|Indicates the task already has a variable with the given name. Use the PUT method to update the task variable instead.|
|415|Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.|

### Update an existing variable on a task

    PUT cmmn-runtime/tasks/{taskId}/variables/{variableName}

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to update the variable for.|
|variableName|Yes|String|The name of the variable to update.|

*Request body for updating simple (non-binary) variables:*

```
{
  "name" : "myTaskVariable",
  "scope" : "local",
  "type" : "string",
  "value" : "Hello World"
}
```

* `name`: Required name of the variable
* `scope`: Scope of variable that is updated. If omitted, +local+ is assumed.
* `type`: Type of variable that is updated. If omitted, reverts to raw JSON-value type (string, boolean, integer or double).
* `value`: Variable value.

|Response code|Description|
|-|-|
|200|Indicates the variables was updated and the result is returned.|
|400|Indicates the name of a variable to update was missing or that an attempt is done to update a variable on a standalone task (without a process associated) with scope +global+. Status message provides additional information.|
|404|Indicates the requested task was not found or the task doesn't have a variable with the given name in the given scope. Status message contains additional information about the error.|

### Updating a binary variable on a task

    PUT cmmn-runtime/tasks/{taskId}/variables/{variableName}

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to update the variable for.|
|variableName|Yes|String|The name of the variable to update.|

*Request body:*

The request should be of type +multipart/form-data+. There should be a single file-part included with the binary value of the variable. On top of that, the following additional form-fields can be present:

* `name`: Required name of the variable.
* `scope`: Scope of variable that is updated. If omitted, +local+ is assumed.
* `type`: Type of variable that is updated. If omitted, +binary+ is assumed and the binary data in the request will be stored as an array of bytes.

|Response code|Description|
|-|-|
|200|Indicates the variable was updated and the result is returned.|
|400|Indicates the name of the variable to update was missing or that an attempt is done to update a variable on a standalone task (without a process associated) with scope +global+. Status message provides additional information.|
|404|Indicates the requested task was not found or the variable to update doesn't exist for the given task in the given scope.|
|415|Indicates the serializable data contains an object for which no class is present in the JVM running the Flowable engine and therefore cannot be deserialized.|

### Delete a variable on a task

    DELETE cmmn-runtime/tasks/{taskId}/variables/{variableName}?scope={scope}

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task the variable to delete belongs to.|
|variableName|Yes|String|The name of the variable to delete.|
|scope|No|String|Scope of variable to delete in. Can be either +local+ or +global+. If omitted, +local+ is assumed.|


|Response code|Description|
|-|-|
|204|Indicates the task variable was found and has been deleted. Response-body is intentionally empty.|
|404|Indicates the requested task was not found or the task doesn't have a variable with the given name. Status message contains additional information about the error.|

### Delete all local variables on a task

    DELETE cmmn-runtime/tasks/{taskId}/variables

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task the variable to delete belongs to.|


|Response code|Description|
|-|-|
|204|Indicates all local task variables have been deleted. Response-body is intentionally empty.|
|404|Indicates the requested task was not found.|

### Get all identity links for a task

    GET cmmn-runtime/tasks/{taskId}/identitylinks


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task to get the identity links for.|

|Response code|Description|
|-|-|
|200|Indicates the task was found and the requested identity links are returned.|
|404|Indicates the requested task was not found.|

*Success response body:*

```
[
    {
        "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/tasks/09688be5-3c78-11ea-8548-38c986587585/identitylinks/users/rest-admin/assignee",
        "user": "rest-admin",
        "group": null,
        "type": "assignee"
    }
]
```


### Get all identitylinks for a task for either groups or users

    GET cmmn-runtime/tasks/{taskId}/identitylinks/users
    GET cmmn-runtime/tasks/{taskId}/identitylinks/groups


Returns only identity links targeting either users or groups. Response body and status-codes are exactly the same as when getting the full list of identity links for a task.


### Get a single identity link on a task

    GET cmmn-runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task .|
|family|Yes|String|Either +groups+ or +users+, depending on what kind of identity is targeted.|
|identityId|Yes|String|The id of the identity.|
|type|Yes|String|The type of identity link.|

|Response code|Description|
|-|-|
|200|Indicates the task and identity link was found and returned.|
|404|Indicates the requested task was not found or the task doesn't have the requested identityLink. The status contains additional information about this error.|

### Create an identity link on a task

    POST cmmn-runtime/tasks/{taskId}/identitylinks

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task.|

*Request body (user):*

```
{
  "userId" : "kermit",
  "type" : "candidate",
}
```

*Request body (group):*

```
{
  "groupId" : "sales",
  "type" : "candidate",
}
```

|Response code|Description|
|-|-|
|201|Indicates the task was found and the identity link was created.|
|404|Indicates the requested task was not found or the task doesn't have the requested identityLink. The status contains additional information about this error.|

*Success response body:*

```
{
  "userId" : null,
  "groupId" : "sales",
  "type" : "candidate",
  "url" : "http://localhost:8081/flowable-rest/service/runtime/tasks/100/identitylinks/groups/sales/candidate"
}
```

### Delete an identity link on a task

    DELETE cmmn-runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|Yes|String|The id of the task.|
|family|Yes|String|Either +groups+ or +users+, depending on what kind of identity is targeted.|
|identityId|Yes|String|The id of the identity.|
|type|Yes|String|The type of identity link.|

|Response code|Description|
|-|-|
|204|Indicates the task and identity link were found and the link has been deleted. Response-body is intentionally empty.|
|404|Indicates the requested task was not found or the task doesn't have the requested identityLink. The status contains additional information about this error.|

## History

### List of historic case instances

    GET cmmn-history/historic-case-instances

URL parameters:

|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|An id of the historic case instance.
|caseDefinitionKey|No|String|The case definition key of the historic case instance.
|caseDefinitionId|No|String|The case definition id of the historic case instance.
|businessKey|No|String|The business key of the historic case instance.
|involvedUser|No|String|An involved user of the historic case instance.
|finished|No|Boolean|Indication if the historic case instance is finished.
|finishedAfter|No|Date|Return only historic case instances that were finished after this date.
|finishedBefore|No|Date|Return only historic case instances that were finished before this date.
|startedAfter|No|Date|Return only historic case instances that were started after this date.
|startedBefore|No|Date|Return only historic case instances that were started before this date.
|startedBy|No|String|Return only historic case instances that were started by this user.
|includeCaseVariables|No|Boolean|An indication if the historic case instance variables should be returned as well.
|tenantId|No|String|Only return instances with the given tenantId.
|tenantIdLike|No|String|Only return instances with a tenantId like the given value.
|withoutTenantId|No|Boolean|If +true+, only returns instances without a tenantId set. If +false+, the +withoutTenantId+ parameter is ignored.

|Response code|Description|
|-|-|
|200|Indicates that historic case instances could be queried.|
|400|Indicates an parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

```
{
    "data": [
        {
            "id": "095fd94e-3c78-11ea-8548-38c986587585",
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-case-instances/095fd94e-3c78-11ea-8548-38c986587585",
            "name": null,
            "businessKey": null,
            "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionName": "Test Case",
            "caseDefinitionDescription": null,
            "startTime": "2020-01-21T19:01:23.923+01:00",
            "endTime": null,
            "startUserId": "rest-admin",
            "superProcessInstanceId": null,
            "variables": [],
            "tenantId": "",
            "state": "active",
            "callbackId": null,
            "callbackType": null,
            "referenceId": null,
            "referenceType": null
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "caseInstanceId",
    "order": "asc",
    "size": 1
}
```

### Query for historic case instances

    POST query/historic-case-instances

*Request body:*

```
{
  "caseDefinitionKey" : "myCase",


  "variables" : [
    {
      "name" : "myVariable",
      "value" : 1234,
      "operation" : "equals",
      "type" : "long"
    }
  ]
}
```

All supported JSON parameter fields allowed are exactly the same as the parameters in the previous section, but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri's that are too long. On top of that, the query allows for filtering based on case variables. The +variables+ property is a JSON-array containing objects using the regular Flowable REST format.


|Response code|Description|
|-|-|
|200|Indicates request was successful and the tasks are returned|
|400|Indicates an parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

### Get a historic case instance

    GET cmmn-history/historic-case-instances/{caseInstanceId}
    
|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|The id of the historic case instance.|    

|Response code|Description|
|-|-|
|200|Indicates that the historic case instances could be found.|
|404|Indicates that the historic case instances could not be found.|

*Success response body:*

```
{
    "id": "095fd94e-3c78-11ea-8548-38c986587585",
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-case-instances/095fd94e-3c78-11ea-8548-38c986587585",
    "name": null,
    "businessKey": null,
    "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
    "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585",
    "caseDefinitionName": "Test Case",
    "caseDefinitionDescription": null,
    "startTime": "2020-01-21T19:01:23.923+01:00",
    "endTime": null,
    "startUserId": "rest-admin",
    "superProcessInstanceId": null,
    "variables": [],
    "tenantId": "",
    "state": "active",
    "callbackId": null,
    "callbackType": null,
    "referenceId": null,
    "referenceType": null
}
```

### Delete a historic case instance

    DELETE cmmn-history/historic-case-instances/{caseInstanceId}

|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|The id of the historic case instance.|    

|Response code|Description|
|-|-|
|200|Indicates that the historic case instance was deleted.|
|404|Indicates that the historic case instance could not be found.|

### Get the identity links of a historic case instance

    GET cmmn-history/historic-case-instance/{caseInstanceId}/identitylinks

|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|The id of the historic case instance.|    

|Response code|Description|
|-|-|
|200|Indicates request was successful and the identity links are returned.|
|404|Indicates the case instance could not be found.|

*Success response body:*

```
[
    {
        "type": "starter",
        "userId": "rest-admin",
        "groupId": null,
        "taskId": null,
        "taskUrl": null,
        "caseInstanceId": "095fd94e-3c78-11ea-8548-38c986587585",
        "caseInstanceUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-case-instances/095fd94e-3c78-11ea-8548-38c986587585"
    },
    {
        "type": "participant",
        "userId": "rest-admin",
        "groupId": null,
        "taskId": null,
        "taskUrl": null,
        "caseInstanceId": "095fd94e-3c78-11ea-8548-38c986587585",
        "caseInstanceUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-case-instances/095fd94e-3c78-11ea-8548-38c986587585"
    }
]
```

### Get the binary data for a historic case instance variable

    GET cmmn-history/historic-case-instances/{caseInstanceId}/variables/{variableName}/data

|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|The id of the historic case instance.|
|variableName|The name of the variable of which the data needs to be returned.|

|Response code|Description|
|-|-|
|200|Indicates the case instance was found and the requested variable data is returned.|
|404|Indicates the requested case instance was not found or the case instance doesn't have a variable with the given name or the variable doesn't have a binary stream available. Status message provides additional information.|

*Success response body:*

The response body contains the binary value of the variable. When the variable is of type +binary+, the content-type of the response is set to +application/octet-stream+, regardless of the content of the variable or the request accept-type header. In case of +serializable+, +application/x-java-serialized-object+ is used as content-type.


### Get the stage overview for a historic case instance

    GET cmmn-history/historic-case-instances/{caseInstanceId}/stage-overview
    
|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|The id of the historic case instance.|    

*Success response body:*

```
[
    {
        "id": "stage1",
        "name": "First Stage",
        "current": true
        "ended": false,
        "endTime": null,
    },
    {
        "id": "stage2",
        "name": "Second stage",
        "current": false
        "ended": false,
        "endTime": null,
    }
]
```

### List of historic milestones

    GET cmmn-history/historic-milestone-instances
    
Note: a milestone is in fact represented as a plan item instance.    
    
|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|Only return milestone instances which belong to the case instance with the given id.|
|caseDefinitionId|No|String|Only return milestone instances which belong to the case definition with the given id.|
|mileStoneId|No|String|Only return milestone instances with the given id (i.e. plan item instance id).|
|mileStoneName|No|String|Only return milestone instances with the given name.|
|reachedBefore|No|Date|Only return milestone instances that have been reached before the provided date.|
|reachedBefore|No|Date|Only return milestone instances that have been reached after the provided date.|

|Response code|Description|
|-|-|
|200|Indicates the milestone instance was found and the requested variable data is returned.|
|404|The milestone instance was not found.|

*success response body:* 

```
{
    "data": [
        {
            "id": "095fd94e-3c78-11ea-8548-38c986587585",
            "name": "My milestone",
            "elementId": "milestone1",
            "caseInstanceId: "123fd94e-3c78-23ea-8548-38c986587585",
            "caseDefinitionId: "567fd94e-3c78-23ea-8548-38c981236545",
            "timestamp": "2020-01-21T19:01:23.923+01:00"
            ...
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "caseInstanceId",
    "order": "asc",
    "size": 1
}
```

### Get a single historic milestone instance

    GET cmmn-history/historic-milestone-instances/{milestoneInstanceId}
    
|Parameter|Required|Value|Description|
|-|-|-|-|
|milestoneInstanceId|No|String|The id of the historic milestone instance.|       

|Response code|Description|
|-|-|
|200|Indicates the milestone instance was found and the requested variable data is returned.|
|404|The milestone instance was not found.|

*Success response body:*

```
{
    "id": "095fd94e-3c78-11ea-8548-38c986587585",
    "name": "My milestone",
    "elementId": "milestone1",
    "caseInstanceId: "123fd94e-3c78-23ea-8548-38c986587585",
    "caseDefinitionId: "567fd94e-3c78-23ea-8548-38c981236545",
    "timestamp": "2020-01-21T19:01:23.923+01:00"
    ...
}
```

### List historic plan item instances

    GET cmmn-history/historic-planitem-instance
   
URL parameters:       

|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|Only return plan item instances which belong to the case instance with the given id.|
|caseDefinitionId|No|String|Only return plan item instances which belong to the case definition with the given id.|
|planItemInstanceId|No|String|Only return plan item instances with the given id.|
|planItemInstanceName|No|String|Only return plan item instances with the given name.|
|planItemInstanceState|No|String|Only return plan item instances with the given state.|   
|stageInstanceId|No|String|Only return plan item instances part of the stage plan item instance with the given id.|
|elementId|No|String|Only return plan item instances with the give element (i.e. from the model) id.|
|planItemDefinitionId|No|String|Only return plan item instances with the given plan item definition id.|
|planItemDefinitionType|No|String|Only return plan item instances with the given plan item definition type.|
|referenceId|No|String|Only return plan item instances with the given reference id.|
|referenceType|No|String|Only return plan item instances with the given reference type.|
|startUserId|No|Date|Only return plan item instances which were started by the given user.|
|createdBefore|No|Date|Only return plan item instances created before the given date.|
|createdAfter|No|Date|Only return plan item instances created after the given date.|
|tenantId|No|String|Only return plan item instances belonging to the given tenant id.|
|withoutTenantId|No|String|Only return plan item instances not belonging to any tenant.|

Due to the fact a plan item instance can move between different states, following state timestamp parameters are also available (all date parameters):

* lastAvailableBefore
* lastAvailableAfter
* lastEnabledBefore
* lastEnabledAfter
* lastDisabledBefore
* lastDisabledAfter
* lastStartedBefore
* lastStartedAfter
* lastSuspendedBefore
* lastSuspendedAfter
* completedBefore
* completedAfter
* terminatedBefore
* terminatedAfter 
* occurredBefore
* occurredAfter
* exitBefore
* exitAfter
* endedBefore (catch-all for all terminal states)
* endedAfter (catch-all for all terminal states)
  

|Response code|Description|
|-|-|
|200|Indicates request was successful and the identity links are returned.|
|400|Indicates an parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Get a historic plan item instance

    GET cmmn-history/historic-planitem-instances/{planItemInstanceId|
    
|Parameter|Required|Value|Description|
|-|-|-|-|
|planItemInstanceId|No|String|The id of the historic plan item instance.|       

|Response code|Description|
|-|-|
|200|Indicates the milestone instance was found and the requested variable data is returned.|
|404|The plan item instance was not found.|    

*Success response body*

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Get historic task instances

    GET cmmn-history/historic-task-instances


|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|No|String|An id of the historic task instance.
|caseInstanceId|No|String|The case instance id of the historic task instance.
|caseDefinitionId|No|String|The case definition id of the historic task instance.
|taskDefinitionKey|No|String|The task definition key for tasks part of a case
|taskName|No|String|The task name of the historic task instance.
|taskNameLike|No|String|The task name with 'like' operator for the historic task instance.
|taskDescription|No|String|The task description of the historic task instance.
|taskDescriptionLike|No|String|The task description with 'like' operator for the historic task instance.
|taskDefinitionKey|No|String|The task identifier from the case definition for the historic task instance.
|taskCategory|No|String|Select tasks with the given category. Note that this is the task category, not the category of the case definition (namespace within the BPMN Xml).
|taskDeleteReason|No|String|The task delete reason of the historic task instance.
|taskDeleteReasonLike|No|String|The task delete reason with 'like' operator for the historic task instance.
|taskAssignee|No|String|The assignee of the historic task instance.
|taskAssigneeLike|No|String|The assignee with 'like' operator for the historic task instance.
|taskOwner|No|String|The owner of the historic task instance.
|taskOwnerLike|No|String|The owner with 'like' operator for the historic task instance.
|taskInvolvedUser|No|String|An involved user of the historic task instance.
|taskPriority|No|String|The priority of the historic task instance.
|finished|No|Boolean|Indication if the historic task instance is finished.
|caseFinished|No|Boolean|Indication if the case instance of the historic task instance is finished.
|parentTaskId|No|String|An optional parent task id of the historic task instance.
|dueDate|No|Date|Return only historic task instances that have a due date equal this date.
|dueDateAfter|No|Date|Return only historic task instances that have a due date after this date.
|dueDateBefore|No|Date|Return only historic task instances that have a due date before this date.
|withoutDueDate|No|Boolean|Return only historic task instances that have no due-date. When +false+ is provided as value, this parameter is ignored.
|taskCompletedOn|No|Date|Return only historic task instances that have been completed on this date.
|taskCompletedAfter|No|Date|Return only historic task instances that have been completed after this date.
|taskCompletedBefore|No|Date|Return only historic task instances that have been completed before this date.
|taskCreatedOn|No|Date|Return only historic task instances that were created on this date.
|taskCreatedBefore|No|Date|Return only historic task instances that were created before this date.
|taskCreatedAfter|No|Date|Return only historic task instances that were created after this date.
|includeTaskLocalVariables|No|Boolean|An indication if the historic task instance local variables should be returned as well.
|tenantId|No|String|Only return historic task instances with the given tenantId.
|tenantIdLike|No|String|Only return historic task instances with a tenantId like the given value.
|withoutTenantId|No|Boolean|If +true+, only returns historic task instances without a tenantId set. If +false+, the +withoutTenantId+ parameter is ignored.

|Response code|Description|
|-|-|
|200|Indicates that historic case instances could be queried.|
|400|Indicates a parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

```
{
    "data": [
        {
            "id": "09688be5-3c78-11ea-8548-38c986587585",
            "name": "Human task",
            "description": null,
            "deleteReason": null,
            "owner": null,
            "assignee": "rest-admin",
            "startTime": "2020-01-21T19:01:23.975+01:00",
            "endTime": null,
            "durationInMillis": null,
            "workTimeInMillis": null,
            "claimTime": null,
            "taskDefinitionKey": "humanTask1",
            "formKey": null,
            "priority": 50,
            "dueDate": null,
            "parentTaskId": null,
            "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-task-instances/09688be5-3c78-11ea-8548-38c986587585",
            "variables": [],
            "tenantId": "",
            "category": null,
            "caseInstanceId": "095fd94e-3c78-11ea-8548-38c986587585",
            "caseInstanceUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-case-instances/095fd94e-3c78-11ea-8548-38c986587585",
            "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
            "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585"
        }
    ],
    "total": 1,
    "start": 0,
    "sort": "taskInstanceId",
    "order": "asc",
    "size": 1
}
```

### Get a single historic task instance

    GET cmmn-history/historic-task-instances/{taskId}

|Parameter|Required|Value|Description|
|-|-|-|-|
|taskId|No|String|The id of the historic task.|    

|Response code|Description|
|200|Indicates that the historic task instance could be found.
|404|Indicates that the historic task instance could not be found.

*Success response body:*

```
{
    "id": "09688be5-3c78-11ea-8548-38c986587585",
    "name": "Human task",
    "description": null,
    "deleteReason": null,
    "owner": null,
    "assignee": "rest-admin",
    "startTime": "2020-01-21T19:01:23.975+01:00",
    "endTime": null,
    "durationInMillis": null,
    "workTimeInMillis": null,
    "claimTime": null,
    "taskDefinitionKey": "humanTask1",
    "formKey": null,
    "priority": 50,
    "dueDate": null,
    "parentTaskId": null,
    "url": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-task-instances/09688be5-3c78-11ea-8548-38c986587585",
    "variables": [],
    "tenantId": "",
    "category": null,
    "caseInstanceId": "095fd94e-3c78-11ea-8548-38c986587585",
    "caseInstanceUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-case-instances/095fd94e-3c78-11ea-8548-38c986587585",
    "caseDefinitionId": "59fd213c-3c6b-11ea-8548-38c986587585",
    "caseDefinitionUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-repository/case-definitions/59fd213c-3c6b-11ea-8548-38c986587585"
}
```

### Query for historic task instances

    POST query/historic-task-instances

All supported JSON parameter fields allowed are exactly the same as the parameters found in the previous section, but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri's that are too long. On top of that, the query allows for filtering based on case variables.

|Response code|Description|
|-|-|
|200|Indicates request was successful and the tasks are returned.|
|400|Indicates an parameter was passed in the wrong format. The status-message contains additional information.|

### Delete a historic task instance

    DELETE cmmn-history/historic-task-instances/{taskId}

|Response code|Description|
|200|Indicates that the historic task instance was deleted.|
|404|Indicates that the historic task instance could not be found.|

### Get the identity links of a historic task instance

    GET cmmn-history/historic-task-instance/{taskId}/identitylinks

|Response code|Description|
|-|-|
|200|Indicates request was successful and the identity links are returned/|
|404|Indicates the task instance could not be found.|

*Success response body:*

```
[
    {
        "type": "assignee",
        "userId": "rest-admin",
        "groupId": null,
        "taskId": "09688be5-3c78-11ea-8548-38c986587585",
        "taskUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-history/historic-task-instances/09688be5-3c78-11ea-8548-38c986587585",
        "caseInstanceId": null,
        "caseInstanceUrl": null
    }
]
```

### Get the binary data for a historic task instance variable

    GET cmmn-history/historic-task-instances/{taskId}/variables/{variableName}/data

|Response code|Description|
|-|-|
|200|Indicates the task instance was found and the requested variable data is returned.|
|404|Indicates the requested task instance was not found or the case instance doesn't have a variable with the given name or the variable doesn't have a binary stream available. Status message provides additional information.|

*Success response body:*

The response body contains the binary value of the variable. When the variable is of type +binary+, the content-type of the response is set to +application/octet-stream+, regardless of the content of the variable or the request accept-type header. In case of +serializable+, +application/x-java-serialized-object+ is used as content-type.

### List of historic variable instances

    GET cmmn-history/historic-variable-instances

URL parameters:

|Parameter|Required|Value|Description|
|-|-|-|-|
|caseInstanceId|No|String|The case instance id of the historic variable instance.
|taskId|No|String|The task id of the historic variable instance.
|excludeTaskVariables|No|Boolean|Indication to exclude the task variables from the result.
|variableName|No|String|The variable name of the historic variable instance.
|variableNameLike|No|String|The variable name using the 'like' operator for the historic variable instance.

|Response code|Description|
|-|-|
|200|Indicates that historic variable instances could be queried.|
|400|Indicates an parameter was passed in the wrong format. The status-message contains additional information.|

*Success response body:*

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Query for historic variable instances

    POST query/historic-variable-instances

*Request body:*

```
{
  "caseDefinitionId" : "59fd213c-3c6b-11ea-8548-38c986587585",
  ...

  "variables" : [
    {
      "name" : "myVariable",
      "value" : 1234,
      "operation" : "equals",
      "type" : "long"
    }
  ]
}
```


All supported JSON parameter fields allowed are exactly the same as the parameters found in the previous section, but passed in as JSON-body arguments rather than URL-parameters to allow for more advanced querying and preventing errors with request-uri's that are too long. On top of that, the query allows for filtering based on case variables. The +variables+ property is a JSON-array containing objects with the regular Flowable variables format.

|Response code|Description|
|-|-|
|200|Indicates request was successful and the tasks are returned.|
|400|Indicates an parameter was passed in the wrong format. The status-message contains additional information.|

### Get the binary data for a historic task instance variable

    GET cmmn-history/historic-variable-instances/{varInstanceId}/data

|Parameter|Required|Value|Description|
|-|-|-|-|
|varInstanceId|No|String|The historic variable id of which the data is needed.|

|Response code|Description|
|-|-|
|200|Indicates the variable instance was found and the requested variable data is returned.|
|404|Indicates the requested variable instance was not found or the variable instance doesn't have a variable with the given name or the variable doesn't have a binary stream available. Status message provides additional information.|

*Success response body:*

The response body contains the binary value of the variable. When the variable is of type +binary+, the content-type of the response is set to +application/octet-stream+, regardless of the content of the variable or the request accept-type header. In case of +serializable+, +application/x-java-serialized-object+ is used as content-type.

## Job management

The CMMN REST API allows full access to manage async jobs, timer jobs, suspended jobs and deadletter jobs.
The API is exactly the same as the one [for the BPMN engine](../bpmn/ch14-REST#jobs), except `management` is replaced with `cmmn-management`.

---

### Docusaurus Docs Dmn Ch02 Configuration (`docs/docusaurus/docs/dmn/ch02-Configuration.md`)

---
id: ch02-Configuration
title: Configuration
---

## Creating a DMN Engine

*The Flowable DMN engine is structured in a very similar way to the Flowable process engine. As a result, parts of the documentation are very similar to their process engine counterpart.*

The Flowable DMN engine is configured through an XML file named flowable.dmn.cfg.xml. Note that this is **not** applicable if you’re using [the Spring style of building a DMN engine](dmn/ch04-Spring.md#spring-integration).

The easiest way to obtain a DmnEngine, is to use the org.flowable.dmn.engine.DmnEngines class:

    DmnEngine dmnEngine = DmnEngines.getDefaultDmnEngine()

This will look for a flowable.dmn.cfg.xml file on the classpath and construct an engine based on the configuration in that file. The following snippet shows an example configuration. The following sections will give a detailed overview of the configuration properties.

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="jdbcDriver" value="org.h2.Driver" />
        <property name="jdbcUsername" value="sa" />
        <property name="jdbcPassword" value="" />

        <property name="databaseSchemaUpdate" value="true" />

        <property name="strictMode" value="false"/>

      </bean>

    </beans>

Note that the configuration XML is in fact a Spring configuration. **This does not mean that Flowable DMN can only be used in a Spring environment!** We are simply leveraging the parsing and dependency injection capabilities of Spring internally for building up the engine.

The DMNEngineConfiguration object can also be created programmatically using the configuration file. It is also possible to use a different bean ID (for example, see line 3).

    DmnEngineConfiguration.
      createDmnEngineConfigurationFromResourceDefault();
      createDmnEngineConfigurationFromResource(String resource);
      createDmnEngineConfigurationFromResource(String resource, String beanName);
      createDmnEngineConfigurationFromInputStream(InputStream inputStream);
      createDmnEngineConfigurationFromInputStream(InputStream inputStream, String beanName);

It is also possible to not use a configuration file and create a configuration based on
defaults (see [the different supported classes](dmn/ch02-Configuration.md#plug-into-process-engine) for more information).

    DmnEngineConfiguration.createStandaloneDmnEngineConfiguration();
    DmnEngineConfiguration.createStandaloneInMemDmnEngineConfiguration();

All these DmnEngineConfiguration.createXXX() methods return a DmnEngineConfiguration that can be further tweaked if needed. After calling the buildDmnEngine() operation, a DmnEngine is created:

    DmnEngine dmnEngine = DmnEngineConfiguration.createStandaloneInMemDmnEngineConfiguration()
      .setDatabaseSchemaUpdate(DmnEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
      .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
      .buildDmnEngine();

## DmnEngineConfiguration bean

The flowable.dmn.cfg.xml must contain a bean that has the ID 'dmnEngineConfiguration'.

     <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">

This bean is then used to construct the DmnEngine. There are multiple classes available that can be used to define the dmnEngineConfiguration. These classes represent different environments, and set defaults accordingly. It’s best practice to select the class that most closely matches your environment, to minimize the number of properties needed to configure the engine. The following classes are currently available:

-   **org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration**: the process engine is used in a standalone way. Flowable will take care of the transactions. By default, the database will only be checked when the engine boots (and an exception is thrown if there’s no Flowable DMN schema or the schema version is incorrect).

-   **org.flowable.dmn.engine.impl.cfg.StandaloneInMemDmnEngineConfiguration**: this is a convenience class for unit testing purposes. Flowable DMN will take care of the transactions. An H2 in-memory database is used by default. The database will be created and dropped when the engine boots and shuts down. When using this, probably no additional configuration is needed).

-   **org.flowable.dmn.spring.SpringDmnEngineConfiguration**: To be used when the DMN engine is used in a Spring environment. See [the Spring integration section](dmn/ch04-Spring.md#spring-integration) for more information.

## Plug into Process Engine

In addition to running in standalone mode it’s also possible to plug the DMN engine into the Process engine. This makes the Process engine aware of it and other engines. This enables, for example, the deployment of artifacts containing not only BPMN models, but also DMN models, to the Process engine’s deployment service API.

To make the Process engine aware of the DMN engine, the **org.flowable.dmn.engine.configurator.DmnEngineConfigurator** needs to be added to list of configurators in the process engine configuration.

    <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="jdbcDriver" value="org.h2.Driver" />
        <property name="jdbcUsername" value="sa" />
        <property name="jdbcPassword" value="" />
        ...
    </bean>

    <bean id="dmnEngineConfigurator" class="org.flowable.dmn.engine.configurator.DmnEngineConfigurator">
        <property name="dmnEngineConfiguration" ref="dmnEngineConfiguration" />
    </bean>

    <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="configurators">
          <list>
            <ref bean="dmnEngineConfigurator" />
          </list>
        </property>
        ...
    </bean>

## Database configuration

There are two ways to configure the database that the Flowable DMN engine will use. The first option is to define the JDBC properties of the database:

-   **jdbcUrl**: JDBC URL of the database.

-   **jdbcDriver**: implementation of the driver for the specific database type.

-   **jdbcUsername**: username to connect to the database.

-   **jdbcPassword**: password to connect to the database.

The data source that is constructed based on the provided JDBC properties will have the default [MyBatis](http://www.mybatis.org/) connection pool settings. The following attributes can optionally be set to tweak that connection pool (taken from the MyBatis documentation):

-   **jdbcMaxActiveConnections**: The maximum number of active connections that the connection pool can contain at any time. Default is 10.

-   **jdbcMaxIdleConnections**: The maximum number of idle connections that the connection pool can contain at any time.

-   **jdbcMaxCheckoutTime**: The amount of time in milliseconds a connection can be 'checked out' from the connection pool before it is forcefully returned. Default is 20000 (20 seconds).

-   **jdbcMaxWaitTime**: This is a low level setting that gives the pool a chance to print a log status and re-attempt the acquisition of a connection in the case that it is taking unusually long (to avoid failing silently forever if the pool is misconfigured) Default is 20000 (20 seconds).

Example database configuration:

    <property name="jdbcUrl" value="jdbc:h2:mem:flowable_dmn;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />

Our benchmarks have shown that the MyBatis connection pool is not the most efficient or resilient when dealing with a lot of concurrent requests. As such, it is advisable to us a javax.sql.DataSource implementation (such as HikariCP, Tomcat JDBC Connection Pool, and so on) and inject it into the process engine configuration :

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/flowable_dmn" />
      <property name="username" value="flowable" />
      <property name="password" value="flowable" />
      <property name="defaultAutoCommit" value="false" />
    </bean>

    <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">

        <property name="dataSource" ref="dataSource" />
        ...

Note that Flowable DMN does not ship with a library that allows you to define such a data source. So you have to make sure that the libraries are on your classpath.

The following properties can be set, regardless of whether you are using the JDBC or data source approach:

-   **databaseType**: it’s normally not necessary to specify this property as it is automatically detected from the database connection metadata. Should only be specified in case automatic detection fails. Possible values: {h2, mysql, oracle, postgres, mssql, db2}. This setting will determine which create/drop scripts and queries will be used. See [the 'supported databases' section](dmn/ch02-Configuration.md#supported-databases) for an overview of which types are supported.

-   **databaseSchemaUpdate**: allows you to set the strategy to handle the database schema on process engine boot and shutdown.

    -   false (default): Checks the version of the DB schema against the library when the process engine is being created and throws an exception if the versions don’t match.

    -   true: Upon building the process engine, a check is performed and an update of the schema is performed if it is necessary. If the schema doesn’t exist, it is created.

    -   create-drop: Creates the schema when the process engine is being created and drops the schema when the process engine is being closed.

## JNDI Datasource Configuration

By default, the database configuration for Flowable DMN is contained within the db.properties files in the WEB-INF/classes of each web application. This isn’t always ideal because it
requires users to either modify the db.properties in the Flowable source and recompile the WAR file, or explode the WAR and modify the db.properties on every deployment.

By using JNDI (Java Naming and Directory Interface) to obtain the database connection, the connection is fully managed by the Servlet Container and the configuration can be managed outside the war deployment. This also allows more control over the connection parameters than what is provided by the db.properties file.

### Configuration

Configuration of the JNDI datasource will differ depending on what servlet container application you are using. The instructions below will work for Tomcat, but for other container applications, please refer to the documentation for your container app.

If using Tomcat, the JNDI resource is configured within $CATALINA\_BASE/conf/\[enginename\]/\[hostname\]/\[warname\].xml (for the Flowable UI this will usually be $CATALINA\_BASE/conf/Catalina/localhost/flowable-app.xml). The default context is copied from the Flowable WAR file when the application is first deployed, so if it already exists, you will need to replace it. To change the JNDI resource so that the application connects to MySQL instead of H2, for example, change the file to the following:

    <?xml version="1.0" encoding="UTF-8"?>
        <Context antiJARLocking="true" path="/flowable-app">
            <Resource auth="Container"
                name="jdbc/flowableDB"
                type="javax.sql.DataSource"
                description="JDBC DataSource"
                url="jdbc:mysql://localhost:3306/flowable"
                driverClassName="com.mysql.jdbc.Driver"
                username="sa"
                password=""
                defaultAutoCommit="false"
                initialSize="5"
                maxWait="5000"
                maxActive="120"
                maxIdle="5"/>
            </Context>

### JNDI properties

To configure a JNDI Datasource, use the following properties in the properties file for the Flowable UI:

-   spring.datasource.jndi-name=: the JNDI name of the Datasource.

-   datasource.jndi.resourceRef: Set whether the lookup occurs in a J2EE container, in other words, if the prefix "java:comp/env/" needs to be added if the JNDI name doesn’t already contain it. Default is "true".

### Custom properties

System properties can also be used in the flowable.dmn.cfg.xml by using them in the format `${propertyName:defaultValue}`.

    <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
    <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
    <property name="jdbcUsername" value="${jdbc.username:sa}" />
    <property name="jdbcPassword" value="${jdbc.password:}" />

Using this configuration if the property `jdbc.url` is available then it would be used for the `jdbcUrl` of the `DmnEngineConfiguration`.
Otherwise the value after the first `:` would be used.

It is also possible to define locations from where properties can be picked up from the system by using a bean of type org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.

Example configuration with custom location for properties

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/opt/conf/flowable.properties" />
      </bean>

      <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">

        <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
        <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
        <property name="jdbcUsername" value="${jdbc.username:sa}" />
        <property name="jdbcPassword" value="${jdbc.password:}" />

        <property name="databaseSchemaUpdate" value="true" />

        <property name="strictMode" value="false"/>

      </bean>

    </beans>

With this configuration the properties would be first looked up in the /opt/conf/flowable.properties file.

## Supported databases

Listed below are the types (case sensitive!) that Flowable uses to refer to databases.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Flowable DMN database type</th>
<th>Example JDBC URL</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>h2</p></td>
<td><p>jdbc:h2:tcp://localhost/flowable_dmn</p></td>
<td><p>Default configured database</p></td>
</tr>
<tr class="even">
<td><p>mysql</p></td>
<td><p>jdbc:mysql://localhost:3306/flowable_dmn?autoReconnect=true</p></td>
<td><p>Tested using mysql-connector-java database driver</p></td>
</tr>
<tr class="odd">
<td><p>oracle</p></td>
<td><p>jdbc:oracle:thin:@localhost:1521:xe</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>postgres</p></td>
<td><p>jdbc:postgresql://localhost:5432/flowable_dmn</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>db2</p></td>
<td><p>jdbc:db2://localhost:50000/flowable_dmn</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>mssql</p></td>
<td><p>jdbc:sqlserver://localhost:1433;databaseName=flowable_dmn (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) <em>OR</em> jdbc:jtds:sqlserver://localhost:1433/flowable_dmn (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)</p></td>
<td><p>Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver</p></td>
</tr>
</tbody>
</table>

## Creating the database tables

Flowable DMN uses [Liquibase](http://www.liquibase.org) for tracking, managing and applying database schema changes.

The easiest way to create the database tables for your database is to:

-   Add the flowable-dmn-engine JARs to your classpath

-   Add a suitable database driver

-   Add a Flowable configuration file (*flowable.dmn.cfg.xml*) to your classpath, pointing to your database (see [database configuration section](dmn/ch02-Configuration.md#database-configuration))

-   Execute the main method of the *DbSchemaCreate* class

## Database table names explained

The database names of Flowable DMN all start with **ACT\_DMN\_**.

-   ACT\_DMN\_DATABASECHANGELOG: This table is used by Liquibase to track which changesets have been run.

-   ACT\_DMN\_DATABASECHANGELOGLOCK: This table is used by Liquibase to ensure only one instance of Liquibase is running at a time.

-   ACT\_DMN\_DECISION\_TABLE: This table contains the metadata of the deployed decision tables.

-   ACT\_DMN\_DEPLOYMENT: This table contains the deployment metadata.

-   ACT\_DMN\_DEPLOYMENT\_RESOURCE: This table contains the DMN definition resource and metadata.

## Database upgrade

Make sure you make a backup of your database (using your database backup capabilities) before you run an upgrade.

By default, a version check will be performed each time a process engine is created. This typically happens once at boot time of your application or the Flowable webapps. If the Flowable library notices a difference between the library version and the version of the Flowable database tables, then an exception is thrown.

To upgrade, you have to start by putting the following configuration property in your flowable.dmn.cfg.xml configuration file:

    <beans >

      <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
        
        <property name="databaseSchemaUpdate" value="true" />
        
      </bean>

    </beans>

**Also, include a suitable database driver for your database in the classpath.** Upgrade the Flowable DMN libraries in your application. Or start up a new version of Flowable DMN and point it to a database that contains an older version. With databaseSchemaUpdate set to true, Flowable DMN will automatically upgrade the DB schema to the newer version the first time when it notices that libraries and DB schema are out of sync.

## Deployment cache configuration

All decisions are cached (after they’re parsed) to avoid hitting the database every time a decision table is needed and because decision table data doesn’t change. By default, there is no limit on this cache. To limit the decisions cache, add following property

    <property name="decisionCacheLimit" value="10" />

Setting this property will swap the default hashmap cache with a LRU cache that has the provided hard limit. Of course, the best value for this property depends on the total amount of decisions stored and the number of decisions actually used at runtime.

You can also inject your own cache implementation. This must be a bean that implements the org.flowable.dmn.engine.impl.persistence.deploy.DeploymentCache interface:

    <property name="decisionCache">
      <bean class="org.flowable.MyCache" />
    </property>

## Strict mode

By default strict mode is **enabled**. This means that the hit policies will act as described in the DMN 1.1 spec.
It is however possible to disable strict mode.

    <beans>

      <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
        
          <property name="strictMode" value="false"/>
        
      </bean>

    </beans>

The effect will be that a result will not be invalidated when a hit policy constraint is violated. A possible violation will be logged in the audit log as a validation message.

## Custom Flowable Function Delegates

Flowable DMN provides some built-in JUEL Function Delegates. By setting the **customFlowableFunctionDelegates** property on the dmnEngineConfiguration bean you can provide own. These can be used in expressions to execute your own logic.

    <beans>

      <bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
        
        <property name="customFlowableFunctionDelegates">
          <list>
              <bean ref="myOwnFunctionDelegateOne" />
              <bean ref="myOwnFunctionDelegateTwo" />
          </list>
        </property>
        
      </bean>

      <bean id="myOwnFunctionDelegateOne" class="org.acme.MyOwnFunctionDelegateOne" />
      <bean id="myOwnFunctionDelegateTwo" class="org.acme.MyOwnFunctionDelegateTwo" />

    </beans>

Note that the custom Function Delegates must extend from org.flowable.engine.common.impl.el.AbstractFlowableFunctionDelegate.

## Logging

All logging (flowable, spring, mybatis, …​) is routed through SLF4J and allows the selection of the logging-implementation of your choice.

**By default no SFL4J-binding JAR is present in the flowable-engine dependencies; this should be added in your project in order to use the logging framework of your choice.** If no implementation JAR is added, SLF4J will use a NOP-logger, not logging anything at all, other than a warning that nothing will be logged. For more information on these bindings [<http://www.slf4j.org/codes.html#StaticLoggerBinder>](http://www.slf4j.org/codes.html#StaticLoggerBinder).

With Maven, for example, add a dependency like this (here using log4j), note that you still need to add a version:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-reload4j</artifactId>
    </dependency>

The flowable-rest webapp is configured to use Log4j-binding. Log4j is also used when running the tests for all the flowable-\* modules.

**Important note when using a container with commons-logging in the classpath:** In order to route the spring-logging through SLF4J, a bridge is used (see [<http://www.slf4j.org/legacy.html#jclOverSLF4J>](http://www.slf4j.org/legacy.html#jclOverSLF4J)). If your container provides a commons-logging implementation, please follow directions on this page: [<http://www.slf4j.org/codes.html#release>](http://www.slf4j.org/codes.html#release) to ensure stability.

Example when using Maven (version omitted):

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
    </dependency>

---

### Docusaurus Docs Dmn Ch03 API (`docs/docusaurus/docs/dmn/ch03-API.md`)

---
id: ch03-API
title: The Flowable DMN API
---

## The DMN Engine API and services

The DMN engine API is the most common way of interacting with Flowable DMN. The central starting point is the DmnEngine, which can be created in several ways as described in the [configuration section](dmn/ch02-Configuration.md#creating-a-dmn-engine). From the DmnEngine, you can obtain the various other services.
DmnEngine and the services objects are thread safe. So you can keep a reference to one of those for a whole server.

    DmnEngine dmnEngine = DmnEngines.getDefaultDmnEngine();
    DmnRuleService dmnRuleService = dmnEngine.getDmnRuleService();
    DmnRepositoryService dmnRepositoryService = dmnEngine.getDmnRepositoryService();
    DmnManagementService dmnManagementService = dmnEngine.getDmnManagementService();

DmnEngines.getDefaultDmnEngine() will initialize and build a DMN engine the first time it is called and afterwards always return the same DMN engine. Proper creation and closing of all DMN engines can be done with DMNEngines.init() and DMNEngines.destroy().

The DmnEngines class will scan for all flowable.dmn.cfg.xml and flowable-dmn-context.xml files. For all flowable.dmn.cfg.xml files, the DMN engine will be built in the typical Flowable way: DmnEngineConfiguration.createDmnEngineConfigurationFromInputStream(inputStream).buildDmnEngine(). For all flowable-dmn-context.xml files, the DMN engine will be built in the Spring way: First the Spring application context is created and then the DMN engine is obtained from that application context.

All services are stateless. This means that you can easily run Flowable DMN on multiple nodes in a cluster, each going to the same database, without having to worry about which machine actually executed previous calls. Any call to any service is idempotent, regardless of where it is executed.

The **DmnRepositoryService** is probably the first service needed when working with the Flowable DMN engine. This service offers operations for managing and manipulating deployments and DMN definitions. A DMN definition is the root concept of a DMN model (the main concepts of DMN are explained in the &lt;dmn-introduction, DMN introduction section&gt;). It contains the definition of the decision (and its decision table).
A deployment is the unit of packaging within the Flowable DMN engine. A deployment can contain multiple DMN XML files. Deploying a deployment means it is uploaded to the engine, where all DMN definitions are inspected and parsed before being stored in the database. From that point on, the deployment is known to the system and any decision included in the deployment can now be executed.

Furthermore, this service allows you to:

-   Query deployments, DMN definitions and decision tables known to the engine.

-   Retrieve a POJO version of the DMN definition or decision table that can be used to introspect using Java rather than XML.

The **DmnRuleService** provides methods for executing a decision. By providing parameters and input data, the evaluation of a decision can be started.

The **DmnManagementService** is typically not needed when coding custom application using Flowable DMN. It allows you to retrieve information about the engine version, database tables and table metadata.

For more detailed information on the service operations and the DMN engine API, see [the javadocs](http://www.flowable.org/docs/javadocs/index.html).

## Exception strategy

The base exception in Flowable is the org.flowable.engine.FlowableException, an unchecked exception. This exception can be thrown at all times by the API, but 'expected' exceptions that happen in specific methods are documented in [the javadocs](http://www.flowable.org/docs/javadocs/index.html). For example, an extract from DmnRuleService:

    /**
      * Execute a decision identified by it's key.
      *
      * @param  decisionKey      the decision key, cannot be null
      * @param  inputVariables   map with input variables
      * @return                  the {@link RuleEngineExecutionResult} for this execution
      * @throws FlowableObjectNotFoundException
      *            when the decision with given key does not exist.
      * @throws FlowableException
      *           when an error occurs while executing the decision.
      */
    RuleEngineExecutionResult executeDecisionByKey(String decisionKey, Map<String, Object> inputVariables);

In the example above, when a key is passed for which no decisions exist, an exception will be thrown. Also, as the javadoc **explicitly states that decisionKey cannot be null, a FlowableIllegalArgumentException will be thrown when null is passed**.

Even though we want to avoid a big exception hierarchy, the following subclasses are thrown in specific cases. All other errors that occur during process-execution or API-invocation that don’t fit into the possible exceptions below are thrown as regular FlowableExceptions.

-   FlowableOptimisticLockingException: Thrown when an optimistic lock occurs in the data store caused by concurrent access of the same data entry.

-   FlowableClassLoadingException: Thrown when a class requested to load was not found or when an error occurred while loading it.

-   FlowableObjectNotFoundException: Thrown when an object that is requested or acted on does not exist.

-   FlowableIllegalArgumentException: An exception indicating that an illegal argument has been supplied in a Flowable DMN API call, an illegal value was configured in the engine’s configuration or an illegal value has been supplied.

## Query API

There are two ways of querying data from the engine: the query API and native queries. The Query API allows to program completely typesafe queries with a fluent API. You can add various conditions to your queries (all of which are applied together as a logical AND) and precisely one ordering. The following code shows an example:

    List<DmnDeployment> dmnDeployments = dmnRepositoryService.createDeploymentQuery()
        .deploymentNameLike("deployment%")
        .orderByDeployTime()
        .list();

Sometimes you need more powerful queries, for example, queries using an OR operator or restrictions you cannot express using the Query API. For these cases, we introduced native queries, which allow you to write your own SQL queries. The return type is defined by the Query object you use and the data is mapped into the correct objects, such as Deployment, ProcessInstance, Execution, and so on. As the query will be fired at the database, you have to use table and column names as they are defined in the database; this requires some knowledge about the internal data structure and it’s recommended you use native queries with care. The table names can be retrieved through the API to keep the dependency as small as possible.

    long count = dmnRepositoryService.createNativeDeploymentQuery()
        .sql("SELECT count(*) FROM " + dmnManagementService.getTableName(DmnDeploymentEntity.class) + " D1, "
            + dmnManagementService.getTableName(DecisionTableEntity.class) + " D2 "
            + "WHERE D1.ID_ = D2.DEPLOYMENT_ID_ "
            + "AND D1.ID_ = #{deploymentId}")
        .parameter("deploymentId", deployment.getId())
        .count();

## Unit testing

As Flowable DMN is an embeddable Java engine, writing unit tests for DMN definitions is as simple as writing regular unit tests.

Flowable supports the JUnit Jupiter style of unit testing.

In the JUnit Jupiter style one needs to use the org.flowable.dmn.engine.test.FlowableDmnTest annotation
or register the org.flowable.dmn.engine.test.FlowableDmnExtension manually.
The FlowableDmnTest annotation is just a meta-annotation and does the registration of the FlowableDmnExtension
(i.e. it does @ExtendWith(FlowableDmnExtension.class)).
This will make the DmnEngine and the services available as parameters into the test and lifecycle methods
(@BeforeAll, @BeforeEach, @AfterEach, @AfterAll).
Before each test the dmnEngine will be initialized by default with the flowable.dmn.cfg.xml resource on the classpath.
To specify a different configuration file the org.flowable.dmn.engine.test.DmnConfigurationResource
annotation needs to be used (see second example).
Dmn engines are cached statically over multiple unit tests when the configuration resource is the same.

By using FlowableDmnExtension, you can annotate test methods with org.flowable.dmn.engine.test.DmnDeployment
or org.flowable.dmn.engine.test.DmnDeploymentAnnotation.
If both @DmnDeployment and @DmnDeploymentAnnotation are used then the @DmnDeployment
takes precedence and @DmnDeploymentAnnotation will be ignored.
When a test method is annotated with @DmnDeployment,
before each test the dmn files defined in DmnDeployment\#resources will be deployed.
In case there are no resources defined, a resource file of the form testClassName.testMethod.dmn
in the same package as the test class, will be deployed.
At the end of the test, the deployment will be deleted, including all related dmn definitions, executions, and so on.
See the DmnDeployment class for more information.

Taking all that into account, a JUnit Jupiter test looks as follows:

**JUnit Jupiter test with default resource.**

    @FlowableDmnTest
    class MyDecisionTableTest {

      @Test
      @DmnDeploymentAnnotation
      void simpleDmnTest(DmnEngine dmnEngine) {
        DmnRuleService dmnRuleService = dmnEngine.getDmnRuleService();

        Map<String, Object> executionResult = ruleService.createExecuteDecisionBuilder()
                .decisionKey("extensionUsage")
                .variable("inputVariable1", 2)
                .variable("inputVariable2", "test2")
                .executeWithSingleResult();

        Assertions.assertThat(executionResult).containsEntry("output1", "test1");
      }
    }

With JUnit Jupiter you can also inject the id of the deployment (with +org.flowable.dmn.engine.test.DmnDeploymentId+_) into your test and lifecycle methods.

**JUnit Jupiter test with custom resource.**

    @FlowableDmnTest
    @DmnConfigurationResource("flowable.custom.dmn.cfg.xml")
    class MyDecisionTableTest {

      @Test
      @DmnDeploymentAnnotation
      void simpleDmnTest(DmnEngine dmnEngine) {
        DmnRuleService dmnRuleService = dmnEngine.getDmnRuleService();

        Map<String, Object> executionResult = ruleService.createExecuteDecisionBuilder()
                .decisionKey("extensionUsage")
                .variable("inputVariable1", 2)
                .variable("inputVariable2", "test2")
                .executeWithSingleResult();

        Assertions.assertThat(executionResult).containsEntry("output1", "test1");
      }
    }

## The DMN engine in a web application

The DmnEngine is a thread-safe class and can easily be shared among multiple threads. In a web application, this means it is possible to create the DMN engine once when the container boots and shut down the engine when the container goes down.

The following code snippet shows how you can write a simple ServletContextListener to initialize and destroy process engines in a plain Servlet environment:

    public class DmnEnginesServletContextListener implements ServletContextListener {

      public void contextInitialized(ServletContextEvent servletContextEvent) {
        DmnEngines.init();
      }

      public void contextDestroyed(ServletContextEvent servletContextEvent) {
        DmnEngines.destroy();
      }

    }

The contextInitialized method will delegate to DmnEngines.init(). This will look for flowable.dmn.cfg.xml resource files on the classpath, and create a DmnEngine for the given configurations (for example, multiple JARs with a configuration file). If you have multiple such resource files on the classpath, make sure they all have different names. When the DMN engine is needed, it can be fetched using:

    DmnEngines.getDefaultDmnEngine()

or:

    DmnEngines.getDmnEngine("myName");

Of course, it’s also possible to use any of the variants of creating a DMN engine,
as described in the [configuration section](dmn/ch02-Configuration.md#creating-a-dmn-engine).

The contextDestroyed method of the context-listener delegates to DmnEngines.destroy(). That will properly close all initialized DMN engines.

---

### Docusaurus Docs Dmn Ch04 Spring (`docs/docusaurus/docs/dmn/ch04-Spring.md`)

---
id: ch04-Spring
title: Spring integration
---

While you can definitely use Flowable DMN without Spring, we’ve provided some very nice integration features that are explained in this chapter.

## DmnEngineFactoryBean

The DmnEngine can be configured as a regular Spring bean. The starting point of the integration is the class org.flowable.dmn.spring.DmnEngineFactoryBean. This bean takes a DMN engine configuration and creates the DMN engine. This means that the creation and configuration of properties for Spring is the same as documented in the [configuration section](dmn/ch02-Configuration.md#creating-a-dmn-engine). For Spring integration, the configuration and engine beans will look like this:

    <bean id="dmnEngineConfiguration" class="org.flowable.dmn.spring.SpringDmnEngineConfiguration">
        ...
    </bean>

    <bean id="dmnEngine" class="org.flowable.dmn.spring.DmnEngineFactoryBean">
      <property name="dmnEngineConfiguration" ref="dmnEngineConfiguration" />
    </bean>

Note that the dmnEngineConfiguration bean now uses the org.flowable.dmn.spring.SpringDmnEngineConfiguration class.

## Automatic resource deployment

Spring integration also has a special feature for deploying resources. In the DMN engine configuration, you can specify a set of resources. When the DMN engine is created, all these resources will be scanned and deployed. There is filtering in place that prevents duplicate deployments. Only when the resources have actually changed will new deployments be deployed to the Flowable DMN DB. This makes sense in a lot of use case, where the Spring container is rebooted often (for example, testing).

Here’s an example:

    <bean id="dmnEngineConfiguration" class="org.flowable.spring.SpringDmnEngineConfiguration">
      ...
      <property name="deploymentResources"
        value="classpath*:/org/flowable/spring/test/autodeployment/autodeploy/decision*.dmn" />
    </bean>

    <bean id="dmnEngine" class="org.flowable.dmn.spring.DmnEngineFactoryBean">
      <property name="dmnEngineConfiguration" ref="dmnEngineConfiguration" />
    </bean>

By default, the configuration above will group all of the resources matching the filtering into a single deployment to the Flowable DMN engine. The duplicate filtering to prevent re-deployment of unchanged resources applies to the whole deployment. In some cases, this may not be what you want. For instance, if you deploy a set of DMN resources this way, and only a single
DMN definition in those resources has changed, the deployment as a whole will be considered new and all of the process definitions in that deployment will be re-deployed, resulting in new versions of each of the DMN definitions, even though only one was actually changed.

To be able to customize the way deployments are determined, you can specify an additional property in the SpringDmnEngineConfiguration, deploymentMode. This property defines the way deployments will be determined from the set of resources that match the filter. There are three values that are supported by default for this property:

-   default: Group all resources into a single deployment and apply duplicate filtering to that deployment. This is the default value and it will be used if you don’t specify a value.

-   single-resource: Create a separate deployment for each individual resource and apply duplicate filtering to that deployment. This is the value you would use to have each DMN definition be deployed separately and only create a new DMN definition version if it has changed.

-   resource-parent-folder: Create a separate deployment for resources that share the same parent folder and apply duplicate filtering to that deployment. This value can be used to create separate deployments for most resources, but still be able to group some by placing them in a shared folder. Here’s an example of how to specify the single-resource configuration for deploymentMode:



    <bean id="dmnEngineConfiguration"
        class="org.flowable.dmn.spring.SpringDmnEngineConfiguration">
      ...
      <property name="deploymentResources" value="classpath*:/flowable/*.dmn" />
      <property name="deploymentMode" value="single-resource" />
    </bean>

In addition to using the values listed above for deploymentMode, you may want customized behavior towards determining deployments. If so, you can create a subclass of SpringDmnEngineConfiguration and override the getAutoDeploymentStrategy(String deploymentMode) method. This method determines which deployment strategy is used for a certain value of the deploymentMode configuration.

## Unit testing

When integrating with Spring, decisions can be tested very easily using the standard [Flowable testing facilities](dmn/ch03-API.md#unit-testing).
The following examples show how a decision is tested in typical Spring-based JUnit Jupiter tests:

**JUnit Jupiter test.**

    @ExtendWith(FlowableDmnSpringExtension.class)
    @SpringJUnitConfig(DmnSpringJunitJupiterTest.TestConfiguration.class)
    public class SpringJunit4Test {

        @Autowired
        private DmnEngine dmnEngine;

        @Autowired
        private DmnRuleService ruleService;

        @Test
        @DmnDeploymentAnnotation
        public void simpleDecisionTest() {
            Map<String, Object> executionResult = ruleService.createExecuteDecisionBuilder()
                .decisionKey("extensionUsage")
                .variable("inputVariable1", 2)
                .variable("inputVariable2", "test2")
                .executeWithSingleResult();

            Assertions.assertThat(executionResult).containsEntry("output1", "test1");
        }
    }

---

### Docusaurus Docs Dmn Ch05 Deployment (`docs/docusaurus/docs/dmn/ch05-Deployment.md`)

---
id: ch05-Deployment
title: Deployment
---

## DMN Definitions

DMN Definitions with .dmn extension can be deployed to the DMN engine.

When the DMN engine is plugged into the Process engine, the DMN definitions can be packed into a business archive (BAR) together with other process related resources. The Process engine deployment service will take care of deploying the DMN resources to the DMN engine.

> **Note**
>
> Java classes used for custom expression functions present in the business archive **will not be added to the classpath**. All custom classes used in expressions in decisions in the business archive should be present on the Flowable (DMN) Engine classpath in order to run the decisions.

### DMN Definitions, decisions and decision tables

A DMN definition consists, amongst other things, of decisions. A decision has one expression. The DMN spec describes several types of expressions. Currently in Flowable DMN we support the decision table type of expression.
When deploying a DMN definition, every decision, which can contain one **decision table**, is inserted separately into the ACT\_DMN\_DECISION table.

### Deploying programmatically

Deploying a DMN definition can be done like this:

    String dmnDefinition = "path/to/definition-one.dmn"; //Don't forget the .dmn extension!

    repositoryService.createDeployment()
        .name("Deployment of DMN definition-one")
        .addClasspathResource(dmnDefinition)
        .deploy();

You can use other methods to add the DMN definitions to the deployment like `addInputStream`. This is an example to deploy a DMN definition from an external file:

    File dmnFile = new File("/path/to/definition-two.dmn"); //Don't forget the .dmn extension!

    repositoryService.createDeployment()
        .name("Deployment of DMN definition-two")
        .addInputStream(dmnFile.getName(), new FileInputStream(dmnFile))
        .deploy();

The name of the deployment can be any text but the resource name must always contain a valid DMN resource name suffix (".dmn").

### Java classes

All classes that contain the custom expression functions that are used in your decisions should be present on the engine’s classpath when a decision is executed.

During deployment of a DMN definition, however, these classes don’t have to be present on the classpath.

When you are using the demo setup and you want to add your custom classes, you should add a JAR containing your classes to the flowable-app-rest webapp lib. Don’t forget to include the dependencies of your custom classes (if any) as well. Alternatively, you can include your dependencies in the libraries directory of your Tomcat installation, ${tomcat.home}/lib.

### Creating a single app

Instead of making sure that all DMN engines have all the delegation classes on their classpath and use the right Spring configuration, you may consider including the flowable-rest webapp inside your own webapp so that there is only a single DmnEngine.

## Versioning of DMN decisions

DMN doesn’t have a notion of versioning. That is actually good, because the executable DMN definition file will probably live in a version control system repository (such as Subversion, Git or Mercurial) as part of your development project. Versions of DMN decisions are created during deployment. During deployment, Flowable will assign a version to the decision before it’s stored in the Flowable DB.

For each DMN decision in a DMN definition, the following steps are performed to initialize the properties key, version, name and id:

-   The decision id attribute in the definition XML file is used as the decision table key property.

-   The decision name attribute in the XML file is used as the decision table name property.

-   The first time a decision with a particular key is deployed, version 1 is assigned. For all subsequent deployments of decisions with the same key, the version will be set 1 higher than the maximum currently deployed version. The key property is used to distinguish decisions.

-   The id property is a unique number to guarantee uniqueness of the decision table identifier for the decision table caches in a clustered environment.

Take for example the following process:

    <definitions id="myDefinitions" >
      <decision id="myDecision" name="My important decision" >
        <decisionTable id="decisionTable1" hitPolicy="FIRST" >
        ...

When deploying this decision, the decision table in the database will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>e29d4126-ed4d-11e6-9e00-7282cbd6ce64</p></td>
<td><p>myDecision</p></td>
<td><p>My important decision</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Suppose we now deploy an updated version of the same process (for example, changing some user tasks), but the id of the process definition remains the same. The process definition table will now contain the following entries:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>e29d4126-ed4d-11e6-9e00-7282cbd6ce64</p></td>
<td><p>myDecision</p></td>
<td><p>My important decision</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>e9c2a6c0-c085-11e6-9096-6ab56fad108a</p></td>
<td><p>myDecision</p></td>
<td><p>My important decision</p></td>
<td><p>2</p></td>
</tr>
</tbody>
</table>

When the dmnRuleService.executeDecisionByKey("myDecision") is called, it will now use the decision definition with version 2, as this is the latest version of the decision definition.

If we create a second decision, as defined below and deploy this to Flowable DMN, a third row will be added to the table.

    <definitions id="myNewDefinitions" >
      <decision id="myNewDecision" name="My important decision" >
        <decisionTable id="decisionTable1" hitPolicy="FIRST" >
          ...

The table will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>e29d4126-ed4d-11e6-9e00-7282cbd6ce64</p></td>
<td><p>myDecision</p></td>
<td><p>My important decision</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>e9c2a6c0-c085-11e6-9096-6ab56fad108a</p></td>
<td><p>myDecision</p></td>
<td><p>My important decision</p></td>
<td><p>2</p></td>
</tr>
<tr class="odd">
<td><p>d317d3f7-e948-11e6-9ce6-b28c070b517d</p></td>
<td><p>myNewDecision</p></td>
<td><p>My important decision</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Note how the key for the new decision is different from our first decision. Even though the name is the same (we should probably have changed that too), Flowable DMN only considers the id attribute when distinguishing decisions. The new decision is therefore deployed with version 1.

## Category

Both DMN deployments and decision tables can have user defined categories.
The deployment category can be specified in the API like this:

    dmnRepository
        .createDeployment()
        .category("yourCategory")
        ...
        .deploy();

The decision table category can be specified in the API like this:

    dmnRepository.setDecisionTableCategory("e9c2a6c0-c085-11e6-9096-6ab56fad108a", "yourCategory");

---

### Docusaurus Docs Dmn Ch06 DMN Introduction (`docs/docusaurus/docs/dmn/ch06-DMN-Introduction.md`)

---
id: ch06-DMN-Introduction
title: DMN 1.1 Introduction
---

## What is DMN?

Decision Model and Notation (DMN) is a standard published by the [Object Management Group](http://www.omg.org/spec/DMN/1.1). It’s a standard approach for describing and modeling repeatable decisions within organizations to ensure that decision models are interchangeable across organizations.

## What is a DMN definition

The root element of the DMN 1.1 schema is a **definitions** element. Within this element multiple decision definitions can be defined (although we advise you to
have only one decision definition in each file, as this simplifies maintenance later in the development process). Within each decision, one expression can be defined. There are several types of expressions. Within Flowable, currently, the expression type **decision table** is supported.

    <definitions xmlns="http://www.omg.org/spec/DMN/20151101"
      namespace="http://www.flowable.org/dmn"
      name="DetermineDiscount">

      <decision id="DET_DISC_1" name="DetermineDiscount">

        <decisionTable id="determineDiscountTable1" hitPolicy="FIRST">
          ..
        </decisionTable>

      </decision>

    </definitions>

## Creating a DMN definition

It’s possible to create a DMN Definition with a plain text editor, but for this example we’ll start by using the decision table editor included in the Flowable modeler.

We’ll implement a very simple use case: determining the discount percentage based on a customer category.

Start by opening the decision tables section within the Flowable modeler.



And select **Create Decision Table**.



Provide a decision table name and a unique decision table key and select **Create new decision table**.



You’re now ready to define your decision table. Let’s describe what is presented within the editor.

### Hit Policy

In the top left corner you can select a **hit policy**.

There are 7 hit policies available;

**single hit**

-   **F**IRST: multiple (overlapping) rules can match, with different output entries. The first hit by rule order is returned (and evaluation can halt).

-   **U**NIQUE: no overlap is possible and all rules are disjoint. Only a single rule can be matched.

-   **A**NY: there may be overlap, but all of the matching rules show equal output entries for each output, so any match can be used. If the output entries are non-equal, the hit policy is incorrect and the result will be empty and marked as failed. When [strict mode](dmn/ch02-Configuration.md#strict-mode) is disabled the last valid rule be the result. (The violation will be present as a validation message)

-   **P**RIORITY: multiple rules can match, with different output entries. This policy returns the matching rule with the highest output priority. Output priorities are specified in the ordered list of output values, in decreasing order of priority.
    When [strict mode](dmn/ch02-Configuration.md#strict-mode) is disabled and there are no output values defined the first valid rule be the result. (The violation will be present as a validation message)

**multiple hit**

-   **O**UTPUT ORDER: returns all hits in decreasing output priority order. Output priorities are specified in the ordered list of output values in decreasing order of priority.

-   **R**ULE ORDER: returns all hits in rule order.

-   **C**OLLECT: returns all hits in arbitrary order. An operator (‘+’, ‘&lt;’, ‘&gt;’, ‘\#’) can be added to apply a simple function to the outputs. If no operator is present, the result is the list of all the output entries.

    -   \+ (sum): the result of the decision table is the sum of all the distinct outputs.

    -   &lt; (min): the result of the decision table is the smallest value of all the outputs.

    -   &gt; (max): the result of the decision table is the largest value of all the outputs.

    -   \# (count): the result of the decision table is the number of outputs.

(Prior to version 1.2 of the DMN spec the definition of the `count` collect hit policy stated that only distinct outputs were taken into account. You can still force this behaviour by selecting `Force DMN 1.1` when saving a decision table)

### Input and Output expressions

The header of the decision table itself is divided in two sections; blue and green. In the blue section are the **input expressions**; the green the **output expressions**.



Within an input expression, you can define the variable that will be used in the expression of the rule input entries (explained below). It’s possible to define multiple input expressions by selecting **Add Input** (right click option menu or by clicking the plus icon).



Within an output expression, you can define what variable will be created to form the result of a decision table execution (the value of the variable will be determined by the output entry expression; explained below). It’s possible to define multiple output expressions by selecting **Add Output** (right click option menu or by clicking the plus icon).

### Rules

Each rule consists of one or more input entries and one or more output entries.
A input entry is an expression that will be evaluated against the input variable (of that 'column'). When all input entries are evaluated to be true the rule is considered true, and the output entry is evaluated.

> **Note**
>
> The DMN specification defines an expression language: (S)-FEEL. Currently, we do not supported this part of the specification. Within Flowable DMN, we use JUEL as the expression language.



To enter an expression, double-click on the corresponding cell.
In this example, the expression *== BRONZE* is entered. Combined with the variable defined in the corresponding input expression (column header), this will result at runtime in the full expression *customerCat == "BRONZE"*.



To enter an output expression, double-click the corresponding cell.
In this example the expression *5* is entered. This is actually more like an implicit assignment. The value 5 will be assigned to the variable in the corresponding output entry (column) when all input entries of that rule are evaluated true.

We can then continue completing the decision table by adding more rules (by selecting Add Rule).



In our example, rule 4 has an empty input entry. Empty input entries will be evaluated by the engine as true. This means that if none of the other rules are valid, the outcome of rule 4 will be the output of this decision table. In this case, variable **discountPerc** will have value **0**.



The decision table can now be saved. Provide a unique Decision Table key.

## Use in a BPMN2.0 process

The newly created decision table can be used in a BPMN2.0 process by including a **Decision task** and selecting the **Decision table reference**.



In the process above, the process has a start form that will provide the **customer category** to the process instance (and thus to the decision table).
The **Display Discount** user task displays the result of the decision table with an expression form field, using the expression; ${discountperc}.

## DMN 1.1 XML

The full DMN 1.1 XML of the example above.

    <definitions xmlns="http://www.omg.org/spec/DMN/20151101" id="definition_78d09dd7-374c-11e8-b5d8-0242ac120005" name="Determine Discount" namespace="http://www.flowable.org/dmn">
      <decision id="DET_DISC_1" name="Determine Discount">
        <decisionTable id="decisionTable_78d09dd7-374c-11e8-b5d8-0242ac120005" hitPolicy="UNIQUE">
          <input label="Customer Category">
            <inputExpression id="inputExpression_1" typeRef="string">
              <text>customerCat</text>
            </inputExpression>
            <inputValues>
              <text>"BRONZE","SILVER","GOLD"</text>
            </inputValues>
          </input>
          <output id="outputExpression_2" label="Discount Percentage" name="discountPerc" typeRef="number">
            <outputValues>
              <text>"0","5","10","20"</text>
            </outputValues>
          </output>
          <rule>
            <inputEntry id="inputEntry_1_1">
              <text><![CDATA[== "BRONZE"]]></text>
            </inputEntry>
            <outputEntry id="outputEntry_2_1">
              <text><![CDATA[5]]></text>
            </outputEntry>
          </rule>
          <rule>
            <inputEntry id="inputEntry_1_2">
              <text><![CDATA[== "SILVER"]]></text>
            </inputEntry>
            <outputEntry id="outputEntry_2_2">
              <text><![CDATA[10]]></text>
            </outputEntry>
          </rule>
          <rule>
            <inputEntry id="inputEntry_1_3">
              <text><![CDATA[== "GOLD"]]></text>
            </inputEntry>
            <outputEntry id="outputEntry_2_3">
              <text><![CDATA[20]]></text>
            </outputEntry>
          </rule>
          <rule>
            <inputEntry id="inputEntry_1_4">
              <text><![CDATA[-]]></text>
            </inputEntry>
            <outputEntry id="outputEntry_2_4">
              <text><![CDATA[0]]></text>
            </outputEntry>
          </rule>
        </decisionTable>
      </decision>
    </definitions>

-   Important to note here, is that the decision table key used in Flowable is the decision ID in the DMN XML. \*

---

### Docusaurus Docs Dmn Ch07 REST (`docs/docusaurus/docs/dmn/ch07-REST.md`)

---
id: ch07-REST
title: REST API
---

## General Flowable REST principles

### Installation and Authentication

Flowable includes a REST API to the Flowable engine that can be installed by deploying the flowable-rest.war file to a servlet container like Apache Tomcat. However, it can also be used in another web-application by including the servlet (and/or its mappings) in your application and add all flowable-rest dependencies to the classpath.

By default the Flowable engine will connect to an in-memory H2 database. You can change the database settings in the flowable-app.properties file in the *WEB-INF/META-INF/flowable-app* folder. The REST API uses JSON format (<http://www.json.org>) and is built upon the Spring MVC (<http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html>).

All REST-resources require a valid user with the *rest-access-api* privilege to be authenticated by default. If any valid user should be able to call the REST API, the *flowable.rest.app.authentication-mode* can be set to *any-user* (this was the default in older versions of Flowable).

A default user that can access the REST API can be configured by settings the following properties:

    flowable.rest.app.admin.user-id=rest-admin
    flowable.rest.app.admin.password=test
    flowable.rest.app.admin.first-name=Rest
    flowable.rest.app.admin.last-name=Admin

When the REST app boots up, the user is created if it doesn’t exist or fetched otherwise. This user will be given the *access-rest-api* privilege which is needed by default to access the REST API. **Do not forget to change the password of this user afterwards**. If the *flowable.rest.app.admin.user-id* is not set, no users or privileges will be created. So, after the initial setup, removing this property will not remove the user nor the privilege that has been configured before.

Basic HTTP access authentication is used, so you should always include a *Authorization: Basic …​==* HTTP-header when performing requests or include the username and password in the request-url (for example, *<http://username:password@localhost:8080/xyz>*).

**We recommend that you use Basic Authentication in combination with HTTPS.**

### Configuration

The Flowable REST web application uses Spring Java Configuration for starting the Flowable Form engine, defining the basic authentication security using Spring security, and to define the variable converters for specific variable handling.
A small number of properties can be defined by changing the flowable-app.properties file you can find in the WEB-INF/META-INF/flowable-app/flowable-app.properties folder.
If you need more advanced configuration options there’s the possibility to override the default Spring beans in XML in the flowable-custom-context.xml file you can also find in the WEB-INF/classes folder.
An example configuration is already in comments in this file. This is also the place to override the default RestResponseFactory by defining a new Spring bean with the name restResponsefactory and use your custom implementation class for it.

### Usage in Tomcat

Due to [default security properties on Tomcat](http://tomcat.apache.org/tomcat-8.0-doc/security-howto.html), **escaped forward slashes (%2F and %5C) are not allowed by default (400-result is returned).** This may have an impact on the deployment resources and their data-URL, as the URL can potentially contain escaped forward slashes.

When issues are experienced with unexpected 400-results, set the following system-property:

*-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW\_ENCODED\_SLASH=true*

It’s best practice to always set the **Accept** and **Content-Type** (in case of posting/putting JSON) headers to **application/json** on the HTTP requests described below.

### Methods and return-codes

<table>
<caption>HTTP-methods and corresponding operations</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>GET</p></td>
<td><p>Get a single resource or get a collection of resources.</p></td>
</tr>
<tr class="even">
<td><p>POST</p></td>
<td><p>Create a new resource. Also used for executing resource-queries which have a too complex request-structure to fit in the query-URL of a GET-request.</p></td>
</tr>
<tr class="odd">
<td><p>PUT</p></td>
<td><p>Update properties of an existing resource. Also used for invoking actions on an existing resource.</p></td>
</tr>
<tr class="even">
<td><p>DELETE</p></td>
<td><p>Delete an existing resource.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>HTTP-methods response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200 - Ok</p></td>
<td><p>The operation was successful and a response has been returned (GET and PUT requests).</p></td>
</tr>
<tr class="even">
<td><p>201 - Created</p></td>
<td><p>The operation was successful and the entity has been created and is returned in the response-body (POST request).</p></td>
</tr>
<tr class="odd">
<td><p>204 - No content</p></td>
<td><p>The operation was successful and entity has been deleted and therefore there is no response-body returned (DELETE request).</p></td>
</tr>
<tr class="even">
<td><p>401 - Unauthorized</p></td>
<td><p>The operation failed. The operation requires an Authentication header to be set. If this was present in the request, the supplied credentials are not valid or the user is not authorized to perform this operation.</p></td>
</tr>
<tr class="odd">
<td><p>403 - Forbidden</p></td>
<td><p>The operation is forbidden and should not be re-attempted. This implies an issue with authorization not authentication, it’s an operation that is not allowed. Example: deleting a task that is part of a running process is not allowed and will never be allowed, regardless of the user or process/task state.</p></td>
</tr>
<tr class="even">
<td><p>404 - Not found</p></td>
<td><p>The operation failed. The requested resource was not found.</p></td>
</tr>
<tr class="odd">
<td><p>405 - Method not allowed</p></td>
<td><p>The operation failed. The method is not allowed for this resource. For example, trying to update (PUT) a deployment-resource will result in a 405 status.</p></td>
</tr>
<tr class="even">
<td><p>409 - Conflict</p></td>
<td><p>The operation failed. The operation causes an update of a resource that has been updated by another operation, which makes the update no longer valid. Can also indicate a resource that is being created in a collection where a resource with that identifier already exists.</p></td>
</tr>
<tr class="odd">
<td><p>415 - Unsupported Media Type</p></td>
<td><p>The operation failed. The request body contains an unsupported media type. Also occurs when the request-body JSON contains an unknown attribute or value that doesn’t have the right format/type to be accepted.</p></td>
</tr>
<tr class="even">
<td><p>500 - Internal server error</p></td>
<td><p>The operation failed. An unexpected exception occurred while executing the operation. The response-body contains details about the error.</p></td>
</tr>
</tbody>
</table>

The media-type of the HTTP-responses is always application/json unless binary content is requested (for example, deployment resource data), the media-type of the content is used.

### Error response body

When an error occurs (both client and server, 4XX and 5XX status-codes) the response body contains an object describing the error that occurred. An example for a 404-status when a task is not found:

    {
      "statusCode" : 404,
      "errorMessage" : "Could not find a task with id '444'."
    }

### Request parameters

#### URL fragments

Parameters that are part of the URL (for example, the deploymentId parameter in http://host/flowable-rest/dmn-api/dmn-repository/deployments/{deploymentId})
need to be properly escaped (see [URL-encoding or Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding)) in case the segment contains special characters. Most frameworks have this functionality built in, but it should be taken into account. Especially for segments that can contain forward-slashes (for example, deployment resource), this is required.

#### Rest URL query parameters

Parameters added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/dmn-api/dmn-repository/deployments?name=Deployment) can have the following types and are mentioned in the corresponding REST-API documentation:

<table>
<caption>URL query parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. Can contain any valid characters that are allowed in URLs. In the case of a XXXLike parameter, the string should contain the wildcard character % (properly URL-encoded). This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Boolean</p></td>
<td><p>Parameter representing a boolean value. Can be either true or false. All other values other than these will cause a '405 - Bad request' response.</p></td>
</tr>
<tr class="odd">
<td><p>Date</p></td>
<td><p>Parameter representing a date value. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (e.g. 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### JSON body parameters

<table>
<caption>JSON parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. In the case of a XXXLike parameter, the string should contain the wildcard character %. This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value, using a JSON number. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value, using a JSON number. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Date</p></td>
<td><p>Parameter representing a date value, using a JSON text. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (for example, 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### Paging and sorting

Paging and order parameters can be added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/dmn-api/dmn-repository/deployments?sort=name).

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>sort</p></td>
<td><p>different per query implementation</p></td>
<td><p>Name of the sort key, for which the default value and the allowed values are different per query implementation.</p></td>
</tr>
<tr class="even">
<td><p>order</p></td>
<td><p>asc</p></td>
<td><p>Sorting order which can be 'asc' or 'desc'.</p></td>
</tr>
<tr class="odd">
<td><p>start</p></td>
<td><p>0</p></td>
<td><p>Parameter to allow for paging of the result. By default the result will start at 0.</p></td>
</tr>
<tr class="even">
<td><p>size</p></td>
<td><p>10</p></td>
<td><p>Parameter to allow for paging of the result. By default the size will be 10.</p></td>
</tr>
</tbody>
</table>

> **Note**
>
> Bear in mind that the start parameter is used as the offset of the query. For example, to get tasks in three pages of three items each (9 items), we would use:
>
>     GET /runtime/tasks?start=0&size=3
>     GET /runtime/tasks?start=3&size=3
>     GET /runtime/tasks?start=6&size=3

### JSON query variable format

    {
      "name" : "variableName",
      "value" : "variableValue",
      "operation" : "equals",
      "type" : "string"
    }

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>Name of the variable to include in a query. Can be empty in the case where 'equals' is used in some queries to query for resources that have <strong>any variable name</strong> with the given value.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>Yes</p></td>
<td><p>Value of the variable included in the query, should include a correct format for the given type.</p></td>
</tr>
<tr class="odd">
<td><p>operator</p></td>
<td><p>Yes</p></td>
<td><p>Operator to use in query, can have the following values: equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, lessThan, greaterThan, lessThanOrEquals, greaterThanOrEquals and like.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of variable to use. When omitted, the type will be deduced from the value parameter. Any JSON text-values will be considered of type string, JSON booleans of type boolean, JSON numbers of type long or integer depending on the size of the number. We recommended you include an explicit type when in doubt. Types supported out of the box are listed below.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Default query JSON types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as and converted to a java.lang.String.</p></td>
</tr>
<tr class="even">
<td><p>short</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="odd">
<td><p>integer</p></td>
<td><p>Value is treated as and converted to a java.lang.Integer.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as and converted to a java.lang.Long.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as and converted to a java.lang.Double.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as and converted to a java.lang.Boolean.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as and converted to a java.util.Date. The JSON string will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

#### Variable representation

When working with variables (execute decision), the REST API uses some common principles and JSON-format for both reading and writing. The JSON representation of a variable looks like this:

    {
      "name" : "variableName",
      "value" : "variableValue",
      "valueUrl" : "http://...",
      "type" : "string"
    }

<table>
<caption>Variable JSON attributes</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>Yes</p></td>
<td><p>Name of the variable.</p></td>
</tr>
<tr class="even">
<td><p>value</p></td>
<td><p>No</p></td>
<td><p>Value of the variable. When writing a variable and value is omitted, null will be used as value.</p></td>
</tr>
<tr class="odd">
<td><p>valueUrl</p></td>
<td><p>No</p></td>
<td><p>When reading a variable of type binary or serializable, this attribute will point to the URL from where the raw binary data can be fetched.</p></td>
</tr>
<tr class="even">
<td><p>type</p></td>
<td><p>No</p></td>
<td><p>Type of the variable. See table below for additional information on types. When writing a variable and this value is omitted, the type will be deduced from the raw JSON-attribute request type and is limited to either string, double, integer and boolean. We advise you to always include a type to make sure no wrong assumption about the type are made.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Variable Types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>string</p></td>
<td><p>Value is treated as a java.lang.String. Raw JSON-text value is used when writing a variable.</p></td>
</tr>
<tr class="even">
<td><p>integer</p></td>
<td><p>Value is treated as a java.lang.Integer. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>short</p></td>
<td><p>Value is treated as a java.lang.Short. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>long</p></td>
<td><p>Value is treated as a java.lang.Long. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="odd">
<td><p>double</p></td>
<td><p>Value is treated as a java.lang.Double. When writing, JSON number value is used as base for conversion, falls back to JSON text.</p></td>
</tr>
<tr class="even">
<td><p>boolean</p></td>
<td><p>Value is treated as a java.lang.Boolean. When writing, JSON boolean value is used for conversion.</p></td>
</tr>
<tr class="odd">
<td><p>date</p></td>
<td><p>Value is treated as a java.util.Date. When writing, the JSON text will be converted using ISO-8601 date format.</p></td>
</tr>
</tbody>
</table>

It’s possible to support additional variable-types with a custom JSON representation (either simple value or complex/nested JSON object). By extending the initializeVariableConverters() method on org.flowable.dmn.rest.service.api.DmnRestResponseFactory, you can add additional org.flowable.rest.variable.RestVariableConverter classes to support converting your POJOs to a format suitable for transferring through REST and converting the REST-value back to your POJO. The actual transformation to JSON is done by Jackson.

## Deployment

**When using Tomcat, please read [Usage in Tomcat](#usage-in-tomcat).**

### List of DMN Deployments

    GET dmn-repository/deployments

<table>
<caption>URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given name.</p></td>
</tr>
<tr class="even">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a name like the given name.</p></td>
</tr>
<tr class="odd">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given category.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns deployments without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'id' (default), 'name', 'deploytime' or 'tenantId'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>REST Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the request was successful.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id": "03ab310d-c1de-11e6-a4f4-62ce84ef239e",
          "name": null,
          "deploymentTime": "2016-12-14T10:16:37.000+01:00",
          "category": null,
          "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-repository/deployments/03ab310d-c1de-11e6-a4f4-62ce84ef239e",
          "parentDeploymentId": "17510",
          "tenantId": ""
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "id",
      "order": "asc",
      "size": 1
    }

### Get a DMN deployment

    GET dmn-repository/deployments/{deploymentId}

<table>
<caption>Get a deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the deployment to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the deployment was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "name": null,
      "deploymentTime": "2016-12-14T10:16:37.000+01:00",
      "category": null,
      "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-repository/deployments/03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "parentDeploymentId": "17510",
      "tenantId": ""
    }

### Create a new DMN deployment

    POST dmn-repository/deployments

**Request body:**

The request body should contain data of type *multipart/form-data*. There should be exactly one file in the request: any additional files will be ignored. The deployment name is the name of the file-field passed in.

An additional parameter (form-field) can be passed in the request body with name tenantId. The value of this field will be used as the identifier of the tenant in which this deployment is done.

<table>
<caption>Create a new DMN deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the deployment was created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates there was no content present in the request body or the content mime-type is not supported for deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "name": "newDeployment1",
      "deploymentTime": "2016-12-14T10:16:37.000+01:00",
      "category": null,
      "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-repository/deployments/03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "tenantId" : "myTenant"
    }

### Delete a DMN deployment

    DELETE dmn-repository/deployments/{deploymentId}

<table>
<caption>Delete a DMN deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the deployment to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete a DMN deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the deployment was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

### Get a DMN deployment resource content

    GET dmn-repository/deployments/{deploymentId}/resourcedata/{resourceId}

<table>
<caption>Get a deployment resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the deployment the requested resource is part of.</p></td>
</tr>
<tr class="even">
<td><p>resourceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the resource to get the data for. <strong>Make sure you URL-encode the resourceId in case it contains forward slashes. For example, use 'decisions%2Fmy-decision.dmn' instead of 'decisions/my-decision.dmn'.</strong></p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a deployment resource content - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both deployment and resource have been found and the resource data has been returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found or there is no resource with the given identifier present in the deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body will contain the binary resource-content for the requested resource. The response content-type will be the same as the type returned in the resources 'mimeType' property. Also, a content-disposition header is set, allowing browsers to download the file instead of displaying it.

## Decision Tables

### List of decision tables

    GET dmn-repository/decision-tables

<table>
<caption>List of process definitions - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>version</p></td>
<td><p>No</p></td>
<td><p>integer</p></td>
<td><p>Only return process definitions with the given version.</p></td>
</tr>
<tr class="even">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given name.</p></td>
</tr>
<tr class="odd">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a name like the given name.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given key.</p></td>
</tr>
<tr class="odd">
<td><p>keyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a name like the given key.</p></td>
</tr>
<tr class="even">
<td><p>resourceName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given resource name.</p></td>
</tr>
<tr class="odd">
<td><p>resourceNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a name like the given resource name.</p></td>
</tr>
<tr class="even">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with the given category.</p></td>
</tr>
<tr class="odd">
<td><p>categoryLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions with a category like the given name.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return process definitions which are part of a deployment with the given identifier.</p></td>
</tr>
<tr class="even">
<td><p>latest</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Only return the latest process definition versions. Can only be used together with 'key' and 'keyLike' parameters, using any other parameter will result in a 400-response.</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'name' (default), 'id', 'key', 'category', 'deploymentId' and 'version'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of process definitions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the decision tables are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format or that 'latest' is used with other parameters other than 'key' and 'keyLike'. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
            {
          "id": "46b0379c-c0a1-11e6-bc93-6ab56fad108a",
          "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-repository/decision-tables/46b0379c-c0a1-11e6-bc93-6ab56fad108a",
          "category": null,
          "name": "Decision Table One",
          "key": "DecisionTableOne",
          "description": null,
          "version": 3,
          "resourceName": "dmn-DecisionTableOne.dmn",
          "deploymentId": "46aa6b3a-c0a1-11e6-bc93-6ab56fad108a",
          "parentDeploymentId": "5001",
          "tenantId": ""
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Get a decision table

    GET dmn-repository/decision-tables/{decisionTableId}

<table>
<caption>Get a decision table - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>decisionTableId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the decision table to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a decision table - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the decision table was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested decision table was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "46b0379c-c0a1-11e6-bc93-6ab56fad108a",
      "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-repository/decision-tables/46b0379c-c0a1-11e6-bc93-6ab56fad108a",
      "category": null,
      "name": "Decision Table One",
      "key": "DecisionTableOne",
      "description": null,
      "version": 3,
      "resourceName": "dmn-DecisionTableOne.dmn",
      "deploymentId": "46aa6b3a-c0a1-11e6-bc93-6ab56fad108a",
      "parentDeploymentId": "5001",
      "tenantId": ""
    }

### Get a decision table resource content

    GET dmn-repository/decision-tables/{decisionTableId}/resourcedata

<table>
<caption>Get a decision table resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>decisionTableId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the decision table to get the resource data for.</p></td>
</tr>
</tbody>
</table>

**Response:**

Exactly the same response codes/boy as GET dmn-repository/deployment/{deploymentId}/resourcedata/{resourceId}.

### Get a decision table DMN model

    GET dmn-repository/decision-tables/{decisionTableId}/model

<table>
<caption>Get a decision table DMN model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>decisionTableId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the decision table to get the model for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a decision table DMN model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the decision table was found and the model is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested decision table was not found.</p></td>
</tr>
</tbody>
</table>

**Response body:**
The response body is a JSON representation of the org.flowable.dmn.model.DmnDefinition and contains the full DMN definition model.

    {
       "processes":[
          {
             "id":"oneTaskProcess",
             "xmlRowNumber":7,
             "xmlColumnNumber":60,
             "extensionElements":{

             },
             "name":"The One Task Process",
             "executable":true,
             "documentation":"One task process description",

        ]
    }

## DMN Rule Service

### Execute a decision

    POST dmn-rule/execute

**Request body:**

The request body should contain data of type *multipart/form-data*. The decisionKey is required. The tenantId, parentDeploymentId and a map of inputVariables (restVariables) are optional.

**Response body:**

    {
      "resultVariables": [
        [
          {
            "name": "output1",
            "type": "string",
            "value": "result 1"
          }
        ],
        [
          {
            "name": "output1",
            "type": "string",
            "value": "result 2"
          }
        ],
        [
          {
            "name": "output1",
            "type": "string",
            "value": "result 3"
          }
        ]
      ],
      "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-rule/execute"
    }

<table>
<caption>Execute a decision - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the Decision has been executed.</p></td>
</tr>
</tbody>
</table>

### Execute a single result decision

    POST dmn-rule/execute/single-result

**Request body:**

The request body should contain data of type *multipart/form-data*. The decisionKey is required. The tenantId, parentDeploymentId and a map of inputVariables (restVariables) are optional.

When multiple rules are valid the service will respond with a 500 code.
**Note: a single hit with a compound output is valid (see response below)**

**Response body:**

    {
      "resultVariables": [
        {
          "name": "output1",
          "type": "string",
          "value": "compound 1"
        },
        {
          "name": "output2",
          "type": "string",
          "value": "compound 2"
        }
      ],
      "url": "http://localhost:8080/flowable-rest/dmn-api/dmn-rule/execute/single-result"
    }

<table>
<caption>Execute a single result decision - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the Decision has been executed.</p></td>
</tr>
<tr class="even">
<td><p>500</p></td>
<td><p>Indicates the Decision returned multiple results.</p></td>
</tr>
</tbody>
</table>

## Engine

### Get DMN engine info

    GET dmn-management/engine

Returns a read-only view of the DMN engine that is used in this REST-service.

**Success response body:**

    {
       "name":"default",
       "version":"6.6.0",
       "resourceUrl":"file://flowable-dmn/flowable.dmn.cfg.xml",
       "exception":null
    }

<table>
<caption>Get engine information - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the engine information has been returned.</p></td>
</tr>
</tbody>
</table>

---

### Docusaurus Docs Eventregistry Ch02 Configuration (`docs/docusaurus/docs/eventregistry/ch02-Configuration.md`)

---
id: ch02-Configuration
title: Configuration
---

## Creating an Event Registry Engine

*The Flowable Event Registry engine is structured in a very similar way to the Flowable process engine. As a result, parts of the documentation are very similar to their process engine counterpart.*

The Flowable Event Registry engine is configured through an XML file named flowable.eventregistry.cfg.xml. Note that this is **not** applicable if you’re using [the Spring style of building an Event Registry engine](eventregistry/ch04-Spring.md#spring-integration).

The easiest way to obtain a EventRegistryEngine, is to use the org.flowable.eventregistry.engine.EventRegistryEngines class:

    EventRegistryEngine eventRegistryEngine = EventRegistryEngines.getDefaultEventRegistryEngine()

This will look for a flowable.eventregistry.cfg.xml file on the classpath and construct an engine based on the configuration in that file. The following snippet shows an example configuration. The following sections will give a detailed overview of the configuration properties.

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean id="eventRegistryEngineConfiguration" class="org.flowable.eventregistry.impl.cfg.StandaloneEventRegistryEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
        <property name="jdbcDriver" value="org.h2.Driver" />
        <property name="jdbcUsername" value="sa" />
        <property name="jdbcPassword" value="" />

        <property name="databaseSchemaUpdate" value="true" />

        <property name="strictMode" value="false"/>

      </bean>

    </beans>

Note that the configuration XML is in fact a Spring configuration. **This does not mean that Flowable Event Registry can only be used in a Spring environment!** We are simply leveraging the parsing and dependency injection capabilities of Spring internally for building up the engine.

The EventRegistryEngineConfiguration object can also be created programmatically using the configuration file. It is also possible to use a different bean ID (for example, see line 3).

    EventRegistryEngineConfiguration.
      createEventRegistryEngineConfigurationFromResourceDefault();
      createEventRegistryEngineConfigurationFromResource(String resource);
      createEventRegistryEngineConfigurationFromResource(String resource, String beanName);
      createEventRegistryEngineConfigurationFromInputStream(InputStream inputStream);
      createEventRegistryEngineConfigurationFromInputStream(InputStream inputStream, String beanName);

It is also possible to not use a configuration file and create a configuration based on
defaults (see [the different supported classes](eventregistry/ch02-Configuration.md#plug-into-process-engine) for more information).

    EventRegistryEngineConfiguration.createStandaloneEventRegistryEngineConfiguration();
    EventRegistryEngineConfiguration.createStandaloneInMemEventRegistryEngineConfiguration();

All these EventRegistryEngineConfiguration.createXXX() methods return a EventRegistryEngineConfiguration that can be further tweaked if needed. After calling the buildEventRegistryEngine() operation, an EventRegistryEngine is created:

    EventRegistryEngine eventRegistryEngine = EventRegistryEngineConfiguration.createStandaloneInMemEventRegistryEngineConfiguration()
        .setDatabaseSchemaUpdate(EventRegistryEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
        .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
        .buildEventRegistryEngine();

## EventRegistryEngineConfiguration bean

The flowable.eventregistry.cfg.xml must contain a bean that has the ID 'eventRegistryEngineConfiguration'.

     <bean id="eventRegistryEngineConfiguration" class="org.flowable.eventregistry.impl.cfg.StandaloneEventRegistryEngineConfiguration">

This bean is then used to construct the EventRegistryEngine. There are multiple classes available that can be used to define the eventRegistryEngineConfiguration. These classes represent different environments, and set defaults accordingly. It’s best practice to select the class that most closely matches your environment, to minimize the number of properties needed to configure the engine. The following classes are currently available:

-   **org.flowable.eventregistry.impl.cfg.StandaloneEventRegistryEngineConfiguration**: the event registry engine is used in a standalone way. Flowable will take care of the transactions. By default, the database will only be checked when the engine boots (and an exception is thrown if there’s no Flowable Event Registry schema or the schema version is incorrect).

-   **org.flowable.eventregistry.impl.cfg.StandaloneInMemEventRegistryEngineConfiguration**: this is a convenience class for unit testing purposes. Flowable Event Registry will take care of the transactions. An H2 in-memory database is used by default. The database will be created and dropped when the engine boots and shuts down. When using this, probably no additional configuration is needed).

-   **org.flowable.eventregistry.spring.SpringEventRegistryEngineConfiguration**: To be used when the Event Registry engine is used in a Spring environment. See [the Spring integration section](eventregistry/ch04-Spring.md#spring-integration) for more information.

## Plug into Process Engine

The Event Registry is automatically booted when starting the process engine. So there's no additional configuration needed to start the event registry when already using the process engine.
The process engine uses a default EventRegistryEngineConfigurator to start the event registry. This default configurator can be overridden by setting an eventRegistryConfigurator in the process engine configuration.

It's also possible to disable the event registry in the process engine configuration with the disableEventRegistry property.

## Database configuration

There are two ways to configure the database that the Flowable Event Registry engine will use. The first option is to define the JDBC properties of the database:

-   **jdbcUrl**: JDBC URL of the database.

-   **jdbcDriver**: implementation of the driver for the specific database type.

-   **jdbcUsername**: username to connect to the database.

-   **jdbcPassword**: password to connect to the database.

The data source that is constructed based on the provided JDBC properties will have the default [MyBatis](http://www.mybatis.org/) connection pool settings. The following attributes can optionally be set to tweak that connection pool (taken from the MyBatis documentation):

-   **jdbcMaxActiveConnections**: The maximum number of active connections that the connection pool can contain at any time. Default is 10.

-   **jdbcMaxIdleConnections**: The maximum number of idle connections that the connection pool can contain at any time.

-   **jdbcMaxCheckoutTime**: The amount of time in milliseconds a connection can be 'checked out' from the connection pool before it is forcefully returned. Default is 20000 (20 seconds).

-   **jdbcMaxWaitTime**: This is a low level setting that gives the pool a chance to print a log status and re-attempt the acquisition of a connection in the case that it is taking unusually long (to avoid failing silently forever if the pool is misconfigured) Default is 20000 (20 seconds).

Example database configuration:

    <property name="jdbcUrl" value="jdbc:h2:mem:flowable_event;DB_CLOSE_DELAY=1000" />
    <property name="jdbcDriver" value="org.h2.Driver" />
    <property name="jdbcUsername" value="sa" />
    <property name="jdbcPassword" value="" />

Our benchmarks have shown that the MyBatis connection pool is not the most efficient or resilient when dealing with a lot of concurrent requests. As such, it is advisable to us a javax.sql.DataSource implementation (such as HikariCP, Tomcat JDBC Connection Pool, and so on) and inject it into the event registry engine configuration :

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
      <property name="driverClassName" value="com.mysql.jdbc.Driver" />
      <property name="url" value="jdbc:mysql://localhost:3306/flowable_event" />
      <property name="username" value="flowable" />
      <property name="password" value="flowable" />
      <property name="defaultAutoCommit" value="false" />
    </bean>

    <bean id="eventRegistryEngineConfiguration" class="org.flowable.eventregistry.impl.cfg.StandaloneEventRegistryEngineConfiguration">

        <property name="dataSource" ref="dataSource" />
        ...

Note that Flowable Event Registry does not ship with a library that allows you to define such a data source. So you have to make sure that the libraries are on your classpath.

The following properties can be set, regardless of whether you are using the JDBC or data source approach:

-   **databaseType**: it’s normally not necessary to specify this property as it is automatically detected from the database connection metadata. Should only be specified in case automatic detection fails. Possible values: {h2, mysql, oracle, postgres, mssql, db2}. This setting will determine which create/drop scripts and queries will be used. See [the 'supported databases' section](eventregistry/ch02-Configuration.md#supported-databases) for an overview of which types are supported.

-   **databaseSchemaUpdate**: allows you to set the strategy to handle the database schema on process engine boot and shutdown.

    -   false (default): Checks the version of the DB schema against the library when the event registry engine is being created and throws an exception if the versions don’t match.

    -   true: Upon building the event registry engine, a check is performed and an update of the schema is performed if it is necessary. If the schema doesn’t exist, it is created.

    -   create-drop: Creates the schema when the event registry engine is being created and drops the schema when the event registry engine is being closed.

## JNDI Datasource Configuration

By default, the database configuration for Flowable Event Registry is contained within the db.properties files in the WEB-INF/classes of each web application. This isn’t always ideal because it
requires users to either modify the db.properties in the Flowable source and recompile the WAR file, or explode the WAR and modify the db.properties on every deployment.

By using JNDI (Java Naming and Directory Interface) to obtain the database connection, the connection is fully managed by the Servlet Container and the configuration can be managed outside the war deployment. This also allows more control over the connection parameters than what is provided by the db.properties file.

### Configuration

Configuration of the JNDI datasource will differ depending on what servlet container application you are using. The instructions below will work for Tomcat, but for other container applications, please refer to the documentation for your container app.

If using Tomcat, the JNDI resource is configured within $CATALINA\_BASE/conf/\[enginename\]/\[hostname\]/\[warname\].xml (for the Flowable UI this will usually be $CATALINA\_BASE/conf/Catalina/localhost/flowable-app.xml). The default context is copied from the Flowable WAR file when the application is first deployed, so if it already exists, you will need to replace it. To change the JNDI resource so that the application connects to MySQL instead of H2, for example, change the file to the following:

    <?xml version="1.0" encoding="UTF-8"?>
        <Context antiJARLocking="true" path="/flowable-app">
            <Resource auth="Container"
                name="jdbc/flowableDB"
                type="javax.sql.DataSource"
                description="JDBC DataSource"
                url="jdbc:mysql://localhost:3306/flowable"
                driverClassName="com.mysql.jdbc.Driver"
                username="sa"
                password=""
                defaultAutoCommit="false"
                initialSize="5"
                maxWait="5000"
                maxActive="120"
                maxIdle="5"/>
            </Context>

### JNDI properties

To configure a JNDI Datasource, use the following properties in the properties file for the Flowable UI:

-   spring.datasource.jndi-name=: the JNDI name of the Datasource.

-   datasource.jndi.resourceRef: Set whether the lookup occurs in a J2EE container, in other words, if the prefix "java:comp/env/" needs to be added if the JNDI name doesn’t already contain it. Default is "true".

### Custom properties

System properties can also be used in the flowable.eventregistry.cfg.xml by using them in the format `${propertyName:defaultValue}`.

    <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
    <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
    <property name="jdbcUsername" value="${jdbc.username:sa}" />
    <property name="jdbcPassword" value="${jdbc.password:}" />

Using this configuration if the property `jdbc.url` is available then it would be used for the `jdbcUrl` of the `EventRegistryEngineConfiguration`.
Otherwise the value after the first `:` would be used.

It is also possible to define locations from where properties can be picked up from the system by using a bean of type org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.

Example configuration with custom location for properties

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="file:/opt/conf/flowable.properties" />
      </bean>

      <bean id="eventRegistryEngineConfiguration" class="org.flowable.eventregistry.impl.cfg.StandaloneEventRegistryEngineConfiguration">

        <property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
        <property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
        <property name="jdbcUsername" value="${jdbc.username:sa}" />
        <property name="jdbcPassword" value="${jdbc.password:}" />

        <property name="databaseSchemaUpdate" value="true" />

      </bean>

    </beans>

With this configuration the properties would be first looked up in the /opt/conf/flowable.properties file.

## Supported databases

Listed below are the types (case sensitive!) that Flowable uses to refer to databases.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Flowable Event Registry database type</th>
<th>Example JDBC URL</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>h2</p></td>
<td><p>jdbc:h2:tcp://localhost/flowable_event</p></td>
<td><p>Default configured database</p></td>
</tr>
<tr class="even">
<td><p>mysql</p></td>
<td><p>jdbc:mysql://localhost:3306/flowable_event?autoReconnect=true</p></td>
<td><p>Tested using mysql-connector-java database driver</p></td>
</tr>
<tr class="odd">
<td><p>oracle</p></td>
<td><p>jdbc:oracle:thin:@localhost:1521:xe</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>postgres</p></td>
<td><p>jdbc:postgresql://localhost:5432/flowable_event</p></td>
<td></td>
</tr>
<tr class="odd">
<td><p>db2</p></td>
<td><p>jdbc:db2://localhost:50000/flowable_event</p></td>
<td></td>
</tr>
<tr class="even">
<td><p>mssql</p></td>
<td><p>jdbc:sqlserver://localhost:1433;databaseName=flowable_event (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) <em>OR</em> jdbc:jtds:sqlserver://localhost:1433/flowable_event (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)</p></td>
<td><p>Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver</p></td>
</tr>
</tbody>
</table>

## Creating the database tables

Flowable Event Registry uses [Liquibase](http://www.liquibase.org) for tracking, managing and applying database schema changes.

The easiest way to create the database tables for your database is to:

-   Add the flowable-event-registry JARs to your classpath

-   Add a suitable database driver

-   Add a Flowable configuration file (*flowable.eventregistry.cfg.xml*) to your classpath, pointing to your database (see [database configuration section](eventregistry/ch02-Configuration.md#database-configuration))

-   Execute the main method of the *DbSchemaCreate* class

## Database table names explained

The database names of Flowable Event Registry all start with **FLW\_EVENT\_** or **FLW\_CHANNEL\_**.

-   FLW\_EVENT\_DATABASECHANGELOG: This table is used by Liquibase to track which changesets have been run.

-   FLW\_EVENT\_DATABASECHANGELOGLOCK: This table is used by Liquibase to ensure only one instance of Liquibase is running at a time.

-   FLW\_EVENT\_DEFINITION: This table contains the metadata of the deployed event definitions.

-   FLW\_CHANNEL\_DEFINITION: This table contains the metadata of the deployed channel definitions.

-   FLW\_EVENT\_DEPLOYMENT: This table contains the deployment metadata.

-   FLW\_EVENT\_RESOURCE: This table contains the Event Registry definition resources and metadata.

## Database upgrade

Make sure you make a backup of your database (using your database backup capabilities) before you run an upgrade.

By default, a version check will be performed each time an event registry engine is created. This typically happens once at boot time of your application or the Flowable webapps. If the Flowable library notices a difference between the library version and the version of the Flowable database tables, then an exception is thrown.

To upgrade, you have to start by putting the following configuration property in your flowable.dmn.cfg.xml configuration file:

    <beans >

      <bean id="eventRegistryEngineConfiguration" class="org.flowable.eventregistry.impl.cfg.StandaloneEventRegistryEngineConfiguration">
        
        <property name="databaseSchemaUpdate" value="true" />
        
      </bean>

    </beans>

**Also, include a suitable database driver for your database in the classpath.** Upgrade the Flowable Event Registry libraries in your application. Or start up a new version of Flowable Event Registry and point it to a database that contains an older version. With databaseSchemaUpdate set to true, Flowable Event Registry will automatically upgrade the DB schema to the newer version the first time when it notices that libraries and DB schema are out of sync.

## Deployment cache configuration

All event and channel definitions are cached (after they’re parsed) to avoid hitting the database every time such a definition is needed and because these definitions don’t change. By default, there is no limit on this cache. To limit the event definition cache, add following property

    <property name="eventDefinitionCacheLimit" value="10" />

Setting this property will swap the default hashmap cache with a LRU cache that has the provided hard limit. Of course, the best value for this property depends on the total amount of event definitions stored and the number of event definitions actually used at runtime.

You can also inject your own cache implementation. This must be a bean that implements the org.flowable.common.engine.impl.persistence.deploy.DeploymentCache interface:

    <property name="eventDefinitionCache">
      <bean class="org.flowable.MyCache" />
    </property>

The channel definition cache can't be configured with a limit, because all active channel definitions need to be available in the cache.

## Logging

All logging (flowable, spring, mybatis, …​) is routed through SLF4J and allows the selection of the logging-implementation of your choice.

**By default no SFL4J-binding JAR is present in the flowable-engine dependencies; this should be added in your project in order to use the logging framework of your choice.** If no implementation JAR is added, SLF4J will use a NOP-logger, not logging anything at all, other than a warning that nothing will be logged. For more information on these bindings [<http://www.slf4j.org/codes.html#StaticLoggerBinder>](http://www.slf4j.org/codes.html#StaticLoggerBinder).

With Maven, for example, add a dependency like this (here using log4j), note that you still need to add a version:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-reload4j</artifactId>
    </dependency>

The flowable-rest webapp is configured to use Log4j-binding. Log4j is also used when running the tests for all the flowable-\* modules.

**Important note when using a container with commons-logging in the classpath:** In order to route the spring-logging through SLF4J, a bridge is used (see [<http://www.slf4j.org/legacy.html#jclOverSLF4J>](http://www.slf4j.org/legacy.html#jclOverSLF4J)). If your container provides a commons-logging implementation, please follow directions on this page: [<http://www.slf4j.org/codes.html#release>](http://www.slf4j.org/codes.html#release) to ensure stability.

Example when using Maven (version omitted):

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
    </dependency>

---

### Docusaurus Docs Eventregistry Ch03 API (`docs/docusaurus/docs/eventregistry/ch03-API.md`)

---
id: ch03-API
title: The Flowable Event Registry API
---

## The Event Registry Engine API and services

The Event Registry engine API is the most common way of interacting with the Flowable Event Registry. The central starting point is the EventRegistryEngine, which can be created in several ways as described in the [configuration section](eventregistry/ch02-Configuration.md#creating-an-event-registry-engine). From the EventRegistryEngine, you can obtain the various other services.
EventRegistryEngine and the services objects are thread safe. So you can keep a reference to one of those for a whole server.

    EventRegistryEngine eventRegistryEngine = EventRegistryEngines.getDefaultEventRegistryEngine();
    EventRegistry eventRegistry = eventRegistryEngine.getEventRegistry();
    EventRepositoryService eventRepositoryService = eventRegistryEngine.getEventRepositoryService();
    EventManagementService eventManagementService = eventRegistryEngine.getEventManagementService();

EventRegistryEngines.getDefaultEventRegistryEngine() will initialize and build an Event Registry engine the first time it is called and afterwards always return the same Event Registry engine. Proper creation and closing of all Event Registry engines can be done with EventRegistryEngines.init() and EventRegistryEngines.destroy().

The EventRegistryEngines class will scan for all flowable.eventregistry.cfg.xml and flowable-eventregistry-context.xml files. For all flowable.eventregistry.cfg.xml files, the Event Registry engine will be built in the typical Flowable way: EventRegistryEngineConfiguration.createEventRegistryEngineConfigurationFromInputStream(inputStream).buildEventRegistryEngine(). For all flowable-eventregistry-context.xml files, the Event Registry engine will be built in the Spring way: First the Spring application context is created and then the Event Registry engine is obtained from that application context.

All services are stateless. This means that you can easily run the Flowable Event Registry on multiple nodes in a cluster, each going to the same database, without having to worry about which machine actually executed previous calls. Any call to any service is idempotent, regardless of where it is executed.

The **EventRepositoryService** is probably the first service needed when working with the Flowable Event Registry engine. This service offers operations for managing and manipulating deployments and Event and Channel definitions. 
An event definition is used to configure the event payload and correlation parameters and defines the relation to a specific channel definition key.
A channel definition configures the source or target destination of an incoming or outgoing event. For example, a channel definition can define a JMS listener to a JMS queue name **orderQueue**. 
A deployment is the unit of packaging within the Flowable Event Registry engine. A deployment can contain multiple Event and Channel definition JSON files. Deploying a deployment means it is uploaded to the engine, where all Event and Channel definitions are inspected and parsed before being stored in the database. From that point on, the deployment is known to the system and any event and channel definition included in the deployment can now be used.

Furthermore, this service allows you to:

-   Query deployments, Event and Channel definitions known to the engine.

-   Retrieve a POJO version of the Event and Channel definition that can be used to introspect using Java rather than JSON.

The **EventRegistry** provides methods to receive and send event instances. It also provides methods to add and remove event consumers.

The **EventManagementService** is typically not needed when coding custom application using the Flowable Event Registry. It allows you to retrieve information about the engine version, database tables and table metadata.

For more detailed information on the service operations and the Event Registry engine API, see [the javadocs](http://www.flowable.org/docs/javadocs/index.html).

## Exception strategy

The base exception in Flowable is the org.flowable.engine.FlowableException, an unchecked exception. This exception can be thrown at all times by the API, but 'expected' exceptions that happen in specific methods are documented in [the javadocs](http://www.flowable.org/docs/javadocs/index.html).

    /**
      * Retrieves the Java representation of an event definition.
      *
      * @param  eventDefinitionKey      the event definition key, cannot be null
      * @return the event model Java representation.
      */
    EventModel getEventModelByKey(String eventDefinitionKey);

In the example above, when a key is passed for which no event definitions exist, an exception will be thrown. Also, as the javadoc **explicitly states that eventDefinitionKey cannot be null, a FlowableIllegalArgumentException will be thrown when null is passed**.

Even though we want to avoid a big exception hierarchy, the following subclasses are thrown in specific cases. All other errors that occur during execution or API invocation that don’t fit into the possible exceptions below are thrown as regular FlowableExceptions.

-   FlowableOptimisticLockingException: Thrown when an optimistic lock occurs in the data store caused by concurrent access of the same data entry.

-   FlowableClassLoadingException: Thrown when a class requested to load was not found or when an error occurred while loading it.

-   FlowableObjectNotFoundException: Thrown when an object that is requested or acted on does not exist.

-   FlowableIllegalArgumentException: An exception indicating that an illegal argument has been supplied in a Flowable Event Registry API call, an illegal value was configured in the engine’s configuration or an illegal value has been supplied.

## Query API

The Query API allows to program completely typesafe queries with a fluent API. You can add various conditions to your queries (all of which are applied together as a logical AND) and precisely one ordering. The following code shows an example:

    List<EventDeployment> eventDeployments = eventRepositoryService.createDeploymentQuery()
        .deploymentNameLike("deployment%")
        .orderByDeployTime()
        .list();


## Unit testing

As the Flowable Event Registry is an embeddable Java engine, writing unit tests for Event and Channel definitions is as simple as writing regular unit tests.

Flowable supports the JUnit Jupiter style of unit testing.

In the JUnit Jupiter style one needs to register the org.flowable.eventregistry.test.FlowableEventExtension.
Registering the FlowableEventExtension can be done with @ExtendWith(FlowableEventExtension.class).
This will make the EventRegistryEngine and the services available as parameters into the test and lifecycle methods
(@BeforeAll, @BeforeEach, @AfterEach, @AfterAll).
Before each test the eventRegistryEngine will be initialized by default with the flowable.eventregistry.cfg.xml resource on the classpath.
In order to specify a different configuration file the org.flowable.eventregistry.test.EventConfigurationResource
annotation needs to be used (see second example).
Event Registry engines are cached statically over multiple unit tests when the configuration resource is the same.

By using EventRegistryEngine, you can annotate test methods with org.flowable.eventregistry.test.EventDeploymentAnnotation.
When a test method is annotated with @EventDeploymentAnnotation, before each test the event definition files defined in EventDeploymentAnnotation\#resources will be deployed.
In case there are no resources defined, a resource file of the form testClassName.testMethod.event in the same package as the test class, will be deployed.
At the end of the test, the deployment will be deleted, including all related event and channel definitions.
See the EventDeploymentAnnotation class for more information.

In addition, by using EventRegistryEngine, you can annotate test methods with org.flowable.eventregistry.test.ChannelDeploymentAnnotation.
When a test method is annotated with @ChannelDeploymentAnnotation, before each test the channel definition files defined in ChannelDeploymentAnnotation\#resources will be deployed.
In case there are no resources defined, a resource file of the form testClassName.testMethod.channel in the same package as the test class, will be deployed.
At the end of the test, the deployment will be deleted, including all related event and channel definitions.
See the EventDeploymentAnnotation class for more information.

Taking all that in account, a JUnit Jupiter test looks as follows:

**JUnit Jupiter test with default resource.**

    @ExtendWith(FlowableEventExtension.class)
    class MyEventDefinitionTest {

      @Test
      @EventDeploymentAnnotation
      void simpleEventDefinitionTest(EventRegistryEngine eventRegistryEngine) {
          EventRepositoryService repositoryService = eventRegistryEngine.getEventRepositoryService();
          EventDefinition eventDefinition = repositoryService.createEventDefinitionQuery()
                .eventDefinitionKey("myEvent")
                .latestVersion()
                .singleResult();
          assertNotNull(eventDefinition);
          assertEquals("myEvent", eventDefinition.getKey());
          assertEquals(1, eventDefinition.getVersion());
      }
    }

**JUnit Jupiter test with custom resource.**

    @ExtendWith(FlowableEventExtension.class)
    @EventConfigurationResource("flowable.custom.eventregistry.cfg.xml")
    class MyEventDefinitionTest {

      @Test
      @EventDeploymentAnnotation
      void simpleEventDefinitionTest(EventRegistryEngine eventRegistryEngine) {
          EventRepositoryService repositoryService = eventRegistryEngine.getEventRepositoryService();
          EventDefinition eventDefinition = repositoryService.createEventDefinitionQuery()
                .eventDefinitionKey("myEvent")
                .latestVersion()
                .singleResult();
          assertNotNull(eventDefinition);
          assertEquals("myEvent", eventDefinition.getKey());
          assertEquals(1, eventDefinition.getVersion());
      }
    }

## The Event Registry engine in a web application

The EventRegistryEngine is a thread-safe class and can easily be shared among multiple threads. In a web application, this means it is possible to create the Event Registry engine once when the container boots and shut down the engine when the container goes down.

The following code snippet shows how you can write a simple ServletContextListener to initialize and destroy process engines in a plain Servlet environment:

    public class EventRegistryEnginesServletContextListener implements ServletContextListener {

      public void contextInitialized(ServletContextEvent servletContextEvent) {
        EventRegistryEngines.init();
      }

      public void contextDestroyed(ServletContextEvent servletContextEvent) {
        EventRegistryEngines.destroy();
      }

    }

The contextInitialized method will delegate to EventRegistryEngines.init(). This will look for flowable.eventregistry.cfg.xml resource files on the classpath, and create a EventRegistryEngine for the given configurations (for example, multiple JARs with a configuration file). If you have multiple such resource files on the classpath, make sure they all have different names. When the Event Registry engine is needed, it can be fetched using:

    EventRegistryEngines.getDefaultEventRegistryEngine()

or:

    EventRegistryEngines.getEventRegistryEngine("myName");

Of course, it’s also possible to use any of the variants of creating an Event Registry engine,
as described in the [configuration section](eventregistry/ch02-Configuration.md#creating-an-event-registry-engine).

The contextDestroyed method of the context-listener delegates to EventRegistryEngines.destroy(). That will properly close all initialized Event Registry engines.

---

### Docusaurus Docs Eventregistry Ch04 Spring (`docs/docusaurus/docs/eventregistry/ch04-Spring.md`)

---
id: ch04-Spring
title: Spring integration
---

While you can definitely use the Flowable Event Registry without Spring, we’ve provided some very nice integration features that are explained in this chapter.

## EventRegistryFactoryBean

The EventRegistryEngine can be configured as a regular Spring bean. The starting point of the integration is the class org.flowable.eventregistry.spring.EventRegistryFactoryBean. This bean takes an Event Registry engine configuration and creates the Event Registry engine. This means that the creation and configuration of properties for Spring is the same as documented in the [configuration section](eventregistry/ch02-Configuration.md#creating-an-event-registry-engine). For Spring integration, the configuration and engine beans will look like this:

    <bean id="eventEngineConfiguration" class="org.flowable.eventregistry.spring.SpringEventRegistryEngineConfiguration">
        ...
    </bean>

    <bean id="eventRegistryEngine" class="org.flowable.eventregistry.spring.EventRegistryFactoryBean">
      <property name="eventEngineConfiguration" ref="eventEngineConfiguration" />
    </bean>

Note that the eventEngineConfiguration bean now uses the org.flowable.eventregistry.spring.SpringEventRegistryEngineConfiguration class.

## Automatic resource deployment

Spring integration also has a special feature for deploying resources. In the Event Registry engine configuration, you can specify a set of resources. When the Event Registry engine is created, all these resources will be scanned and deployed. There is filtering in place that prevents duplicate deployments. Only when the resources have actually changed will new deployments be deployed to the Flowable Event Registry DB. This makes sense in a lot of use case, where the Spring container is rebooted often (for example, testing).

Here’s an example:

    <bean id="eventEngineConfiguration" class="org.flowable.eventregistry.spring.SpringEventRegistryEngineConfiguration">
      ...
      <property name="deploymentResources"
          value="classpath*:/org/flowable/test/autodeployment/autodeploy/event*.event" />
    </bean>

    <bean id="eventRegistryEngine" class="org.flowable.eventregistry.spring.EventRegistryFactoryBean">
      <property name="eventEngineConfiguration" ref="eventEngineConfiguration" />
    </bean>

By default, the configuration above will group all of the resources matching the filtering into a single deployment to the Flowable Event Registry engine. The duplicate filtering to prevent re-deployment of unchanged resources applies to the whole deployment. In some cases, this may not be what you want. For instance, if you deploy a set of Event Registry resources this way, and only a single
Event or Channel definition in those resources has changed, the deployment as a whole will be considered new and all of the process definitions in that deployment will be re-deployed, resulting in new versions of each of the Event and Channel definitions, even though only one was actually changed.

To be able to customize the way deployments are determined, you can specify an additional property in the SpringEventRegistryEngineConfiguration, deploymentMode. This property defines the way deployments will be determined from the set of resources that match the filter. There are three values that are supported by default for this property:

-   default: Group all resources into a single deployment and apply duplicate filtering to that deployment. This is the default value and it will be used if you don’t specify a value.

-   single-resource: Create a separate deployment for each individual resource and apply duplicate filtering to that deployment. This is the value you would use to have each Event and Channel definition be deployed separately and only create a new Event and Channel definition version if it has changed.

-   resource-parent-folder: Create a separate deployment for resources that share the same parent folder and apply duplicate filtering to that deployment. This value can be used to create separate deployments for most resources, but still be able to group some by placing them in a shared folder. Here’s an example of how to specify the single-resource configuration for deploymentMode:



    <bean id="eventEngineConfiguration"
        class="org.flowable.eventregistry.spring.SpringEventRegistryEngineConfiguration">
      ...
      <property name="deploymentResources" value="classpath*:/flowable/*.event" />
      <property name="deploymentMode" value="single-resource" />
    </bean>

In addition to using the values listed above for deploymentMode, you may want customized behavior towards determining deployments. If so, you can create a subclass of SpringEventRegistryEngineConfiguration and override the getAutoDeploymentStrategy(String deploymentMode) method. This method determines which deployment strategy is used for a certain value of the deploymentMode configuration.

## Unit testing

When integrating with Spring, decisions can be tested very easily using the standard [Flowable testing facilities](eventregistry/ch03-API.md#unit-testing).
The following examples show how a decision is tested in typical Spring-based JUnit Jupiter tests:

**JUnit Jupiter test.**

    @ExtendWith(FlowableEventSpringExtension.class)
    @SpringJUnitConfig(EventRegistryJmsConfiguration.class)
    public class SpringEventRegistryChangeDetectorTest {

      @Autowired
      private EventRegistryEngine eventRegistryEngine;

      @Test
      public void testChangeDetectionRunnableCreatedWhenNotExplicitelyInjected() {
        assertThat(eventRegistryEngine.getEventRegistryEngineConfiguration().getEventRegistryChangeDetectionManager())
            .isInstanceOf(DefaultEventRegistryChangeDetectionManager.class);

        EventRegistryChangeDetectionExecutor eventRegistryChangeDetectionExecutor = eventRegistryEngine
            .getEventRegistryEngineConfiguration().getEventRegistryChangeDetectionExecutor();
        assertThat(eventRegistryChangeDetectionExecutor).isInstanceOf(DefaultSpringEventRegistryChangeDetectionExecutor.class);

        DefaultSpringEventRegistryChangeDetectionExecutor executor = (DefaultSpringEventRegistryChangeDetectionExecutor) 
            eventRegistryChangeDetectionExecutor;
        assertThat(executor.getTaskScheduler()).isInstanceOf(ThreadPoolTaskScheduler.class);
      }
    }

---

### Docusaurus Docs Eventregistry Ch05 Deployment (`docs/docusaurus/docs/eventregistry/ch05-Deployment.md`)

---
id: ch05-Deployment
title: Deployment
---

## Event Registry Definitions

For the Event Registry two types of definitions are supported, Event and Channel definitions.
Event definitions have an .event extension and Channel definitions have a .channel extension.

When the Event Registry engine is used with the Process engine, the Event and Channel definitions can be packed into a business archive (BAR) together with other process related resources. The Process engine deployment service will take care of deploying the Event and Channel resources to the Event Registry engine.

> **Note**
>
> Java classes used for custom expression functions present in the business archive **will not be added to the classpath**. All custom classes used in expressions in event and channel definitions in the business archive should be present on the Flowable (Event Registry) Engine classpath.

### Event Definitions

An Event definition configures the event payload structure and the correlation and tenant detection. 
When deploying an Event definition a new definition is inserted into the FLW\_EVENT\_DEFINITION table.

### Deploying Event definitions programmatically

Deploying an Event definition can be done like this:

    String eventDefinition = "path/to/definition-one.event"; //Don't forget the .event extension!

    repositoryService.createDeployment()
        .name("Deployment of Event definition-one")
        .addClasspathResource(eventDefinition)
        .deploy();

You can use other methods to add the Event definitions to the deployment like `addInputStream`. This is an example to deploy an Event definition from an external file:

    File eventFile = new File("/path/to/definition-two.event"); //Don't forget the .event extension!

    repositoryService.createDeployment()
        .name("Deployment of Event definition-two")
        .addInputStream(eventFile.getName(), new FileInputStream(eventFile))
        .deploy();

The name of the deployment can be any text but the resource name must always contain a valid Event definition resource name suffix (".event").

### Channel Definitions

A Channel definition configures the source or target destination for an incoming or outgoing event.
By default the Flowable Event Registry supports JMS, Kafka and RabbitMQ source and target destinations, but this can be extended with other adapter types as well. 
When deploying a Channel definition a new definition is inserted into the FLW\_CHANNEL\_DEFINITION table.

### Deploying Channel definitions programmatically

Deploying a Channel definition can be done like this:

    String channelDefinition = "path/to/definition-one.channel"; //Don't forget the .channel extension!

    repositoryService.createDeployment()
        .name("Deployment of Channel definition-one")
        .addClasspathResource(channelDefinition)
        .deploy();

You can use other methods to add the Event definitions to the deployment like `addInputStream`. This is an example to deploy an Event definition from an external file:

    File channelFile = new File("/path/to/definition-two.channel"); //Don't forget the .channel extension!

    repositoryService.createDeployment()
        .name("Deployment of Channel definition-two")
        .addInputStream(channelFile.getName(), new FileInputStream(channelFile))
        .deploy();

The name of the deployment can be any text but the resource name must always contain a valid Channel definition resource name suffix (".channel").

### Java classes

All classes that contain the custom expression functions that are used in your Event and Channel should be present on the engine’s classpath when a decision is executed.

During deployment of an Event or Channel definition, however, these classes don’t have to be present on the classpath.

When you are using the demo setup and you want to add your custom classes, you should add a JAR containing your classes to the flowable-app-rest webapp lib. Don’t forget to include the dependencies of your custom classes (if any) as well. Alternatively, you can include your dependencies in the libraries directory of your Tomcat installation, ${tomcat.home}/lib.

### Creating a single app

Instead of making sure that all Event Registry engines have all the delegation classes on their classpath and use the right Spring configuration, 
you may consider including the flowable-rest webapp inside your own webapp so that there is only a single EventRegistryEngine.

## Versioning of Event and Channel definitions

During deployment, Flowable will assign a version to the Event and Channel definitions before storing them in the Flowable DB.

For each Event and Channel definition, the following steps are performed to initialize the properties key, version, name and id:

-   The event or channel key attribute in the definition JSON file is used as the definition key property.

-   The name property in the JSON file is used as the definition name property.

-   The first time an Event or Channel definition with a particular key is deployed, version 1 is assigned. For all subsequent deployments of Event or Channel definitions with the same key, the version will be set 1 higher than the maximum currently deployed version. The key property is used to distinguish Event and Channel definitions.

-   The id property is a unique number to guarantee uniqueness of the Event and Channel definition identifier for the caches in a clustered environment.

Take for example the following process:

    {
        "key": "myEvent",
        "name": "My event",
        ...

When deploying this Event definition, it will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>e29d4126-ed4d-11e6-9e00-7282cbd6ce64</p></td>
<td><p>myEvent</p></td>
<td><p>My event</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Suppose we now deploy an updated version of the same Event definition, but the key of the Event definition remains the same. The Event definition table will now contain the following entries:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>e29d4126-ed4d-11e6-9e00-7282cbd6ce64</p></td>
<td><p>myEvent</p></td>
<td><p>My event</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>e9c2a6c0-c085-11e6-9096-6ab56fad108a</p></td>
<td><p>myEvent</p></td>
<td><p>My event</p></td>
<td><p>2</p></td>
</tr>
</tbody>
</table>

When the eventRegistry.getEventModelByKey("myEvent") is called, it will now use the Event definition with version 2, as this is the latest version of the Event definition.

If we create a second decision, as defined below and deploy this to Flowable DMN, a third row will be added to the table.

    {
        "key": "myNewEvent",
        "name": "My new event",
        ...

The table will look like this:

<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>id</th>
<th>key</th>
<th>name</th>
<th>version</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>e29d4126-ed4d-11e6-9e00-7282cbd6ce64</p></td>
<td><p>myEvent</p></td>
<td><p>My event</p></td>
<td><p>1</p></td>
</tr>
<tr class="even">
<td><p>e9c2a6c0-c085-11e6-9096-6ab56fad108a</p></td>
<td><p>myEvent</p></td>
<td><p>My event</p></td>
<td><p>2</p></td>
</tr>
<tr class="odd">
<td><p>d317d3f7-e948-11e6-9ce6-b28c070b517d</p></td>
<td><p>myNewEvent</p></td>
<td><p>My new event</p></td>
<td><p>1</p></td>
</tr>
</tbody>
</table>

Note how the key for the new Event definition is different from our first Event definition. Even if the name is the same, the Flowable Event Registry only considers the key attribute when distinguishing Event and Channel. The new Event definition is therefore deployed with version 1.

---

### Docusaurus Docs Eventregistry Ch06 EventRegistry Introduction (`docs/docusaurus/docs/eventregistry/ch06-EventRegistry-Introduction.md`)

---
id: ch06-EventRegistry-Introduction
title: Event Registry Introduction
---

## What is the Event Registry?

The Event Registry engine allows for sending and receiving events from any source (with out-of-the-box support for JMS, Kafka, RabbitMQ and receiving events over HTTP) and using these
events in CMMN and BPMN models. For example, it's possible to receive an event from a JMS queue and start a new process instance of a process definition that has a start event defined
that listens to this event type. Or receive an event from a Kafka topic and trigger a boundary event in a specific process instance that matches the correlation definition of the incoming event.
The same possibilities are there for CMMN, with starting a new case instance when a specific event type is received or triggering an event registry listener of a specific case instance.
There are two types of definitions that need to be configured, e.g. Event and Channel definitions.

## What is an Event definition

An Event definition defines the event payload of an incoming or outgoing event in addition to the default key and name properties that identify the event type.
The event payload is defined with an array of name and type objects, with string, integer, double and boolean types supported.
Another part of the event definition is the correlation parameters property, for which an array of parameter objects with a name and type can be defined.
These correlation parameter values are used to match an incoming event to an event subscription of a case or process instance.
An example of an Event definition is the following JSON definition:

    {
      "key": "myEvent",
      "name": "My event",
      "correlationParameters": [
          {
            "name": "customerId",
            "type": "string"
          }
      ],
      "payload": [
          {
            "name": "customerName",
            "type": "string"
          },
          {
            "name": "amount",
            "type": "integer"
          }
      ]
    }

## What is a Channel definition

A Channel definition defines the destination of an incoming or outgoing event in addition to the default key and name properties that identify the channel type.
The destination name is defined together with a type value that specifies the adapter type to be used. Out-of-the-box the JMS, Kafka and RabbitMQ adapter types are supported, but
other adapters can be added as well. For a Channel definition the channel type can be either inbound (incoming events) or outbound (outgoing events).

For an inbound channel definition the event key detection needs to be defined, which configures how the event key can be determined for the incoming event.
This can be a fixed event type value, or the event key can be determined based on a JSON field value or JSON pointer expression.
In a similar way the tenant id detection can be defined for multi tenant Flowable environments. Here also a static tenant id value can be defined, or a JSON field value or JSON pointer expression.
Another part that can be defined for an inbound channel definition is the way the incoming event can be deserialized.
By default JSON and XML are the out-of-the-box supported deserialization options.

For an outbound channel definition the serializer type can be defined, with the supported JSON and XML values.
An example inbound channel JSON definition is:

    {
      "key": "testChannel",
      "category": "channel",
      "name": "Test channel",
      "channelType": "inbound",
      "type": "jms",
      "destination": "test-customer",
      "deserializerType": "json",
      "channelEventKeyDetection": {
          "jsonField": "eventKeyValue"
      }
    }

This example inbound channel definition connects to a JMS queue named **test-customer** and incoming events will be deserialized as JSON for the event payload and the
event key will be determined based on the **eventKeyValue** JSON property in the incoming event payload.

An example outbound channel JSON definition is:

    {
      "key": "outboundCustomer",
      "category": "channel",
      "name": "Test channel",
      "channelType": "outbound",
      "type": "jms",
      "destination": "outbound-customer",
      "serializerType": "json"
    }
    
This example outbound channel definition connects to a JMS queue named **outbound-customer** and outgoing events will be serialized as a JSON event payload.

---

### Docusaurus Docs Eventregistry Ch07 REST (`docs/docusaurus/docs/eventregistry/ch07-REST.md`)

---
id: ch07-REST
title: REST API
---

## General Flowable REST principles

### Installation and Authentication

Flowable includes a REST API to the Flowable engine that can be installed by deploying the flowable-rest.war file to a servlet container like Apache Tomcat. However, it can also be used in another web-application by including the servlet (and/or its mappings) in your application and add all flowable-rest dependencies to the classpath.

By default the Flowable engine will connect to an in-memory H2 database. You can change the database settings in the flowable-app.properties file in the *WEB-INF/META-INF/flowable-app* folder. The REST API uses JSON format (<http://www.json.org>) and is built upon the Spring MVC (<http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html>).

All REST-resources require a valid user with the *rest-access-api* privilege to be authenticated by default. If any valid user should be able to call the REST API, the *flowable.rest.app.authentication-mode* can be set to *any-user* (this was the default in older versions of Flowable).

A default user that can access the REST API can be configured by settings the following properties:

    flowable.rest.app.admin.user-id=rest-admin
    flowable.rest.app.admin.password=test
    flowable.rest.app.admin.first-name=Rest
    flowable.rest.app.admin.last-name=Admin

When the REST app boots up, the user is created if it doesn’t exist or fetched otherwise. This user will be given the *access-rest-api* privilege which is needed by default to access the REST API. **Do not forget to change the password of this user afterwards**. If the *flowable.rest.app.admin.user-id* is not set, no users or privileges will be created. So, after the initial setup, removing this property will not remove the user nor the privilege that has been configured before.

Basic HTTP access authentication is used, so you should always include a *Authorization: Basic …​==* HTTP-header when performing requests or include the username and password in the request-url (for example, *<http://username:password@localhost:8080/xyz>*).

**We recommend that you use Basic Authentication in combination with HTTPS.**

### Configuration

The Flowable REST web application uses Spring Java Configuration for starting the Flowable Form engine, defining the basic authentication security using Spring security, and to define the variable converters for specific variable handling.
A small number of properties can be defined by changing the flowable-app.properties file you can find in the WEB-INF/META-INF/flowable-app/flowable-app.properties folder.
If you need more advanced configuration options there’s the possibility to override the default Spring beans in XML in the flowable-custom-context.xml file you can also find in the WEB-INF/classes folder.
An example configuration is already in comments in this file. This is also the place to override the default RestResponseFactory by defining a new Spring bean with the name restResponsefactory and use your custom implementation class for it.

### Usage in Tomcat

Due to [default security properties on Tomcat](http://tomcat.apache.org/tomcat-8.0-doc/security-howto.html), **escaped forward slashes (%2F and %5C) are not allowed by default (400-result is returned).** This may have an impact on the deployment resources and their data-URL, as the URL can potentially contain escaped forward slashes.

When issues are experienced with unexpected 400-results, set the following system-property:

*-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW\_ENCODED\_SLASH=true*

It’s best practice to always set the **Accept** and **Content-Type** (in case of posting/putting JSON) headers to **application/json** on the HTTP requests described below.

### Methods and return-codes

<table>
<caption>HTTP-methods and corresponding operations</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>GET</p></td>
<td><p>Get a single resource or get a collection of resources.</p></td>
</tr>
<tr class="even">
<td><p>POST</p></td>
<td><p>Create a new resource. Also used for executing resource-queries which have a too complex request-structure to fit in the query-URL of a GET-request.</p></td>
</tr>
<tr class="odd">
<td><p>PUT</p></td>
<td><p>Update properties of an existing resource. Also used for invoking actions on an existing resource.</p></td>
</tr>
<tr class="even">
<td><p>DELETE</p></td>
<td><p>Delete an existing resource.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>HTTP-methods response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200 - Ok</p></td>
<td><p>The operation was successful and a response has been returned (GET and PUT requests).</p></td>
</tr>
<tr class="even">
<td><p>201 - Created</p></td>
<td><p>The operation was successful and the entity has been created and is returned in the response-body (POST request).</p></td>
</tr>
<tr class="odd">
<td><p>204 - No content</p></td>
<td><p>The operation was successful and entity has been deleted and therefore there is no response-body returned (DELETE request).</p></td>
</tr>
<tr class="even">
<td><p>401 - Unauthorized</p></td>
<td><p>The operation failed. The operation requires an Authentication header to be set. If this was present in the request, the supplied credentials are not valid or the user is not authorized to perform this operation.</p></td>
</tr>
<tr class="odd">
<td><p>403 - Forbidden</p></td>
<td><p>The operation is forbidden and should not be re-attempted. This implies an issue with authorization not authentication, it’s an operation that is not allowed. Example: deleting a task that is part of a running process is not allowed and will never be allowed, regardless of the user or process/task state.</p></td>
</tr>
<tr class="even">
<td><p>404 - Not found</p></td>
<td><p>The operation failed. The requested resource was not found.</p></td>
</tr>
<tr class="odd">
<td><p>405 - Method not allowed</p></td>
<td><p>The operation failed. The method is not allowed for this resource. For example, trying to update (PUT) a deployment-resource will result in a 405 status.</p></td>
</tr>
<tr class="even">
<td><p>409 - Conflict</p></td>
<td><p>The operation failed. The operation causes an update of a resource that has been updated by another operation, which makes the update no longer valid. Can also indicate a resource that is being created in a collection where a resource with that identifier already exists.</p></td>
</tr>
<tr class="odd">
<td><p>415 - Unsupported Media Type</p></td>
<td><p>The operation failed. The request body contains an unsupported media type. Also occurs when the request-body JSON contains an unknown attribute or value that doesn’t have the right format/type to be accepted.</p></td>
</tr>
<tr class="even">
<td><p>500 - Internal server error</p></td>
<td><p>The operation failed. An unexpected exception occurred while executing the operation. The response-body contains details about the error.</p></td>
</tr>
</tbody>
</table>

The media-type of the HTTP-responses is always application/json unless binary content is requested (for example, deployment resource data), the media-type of the content is used.

### Error response body

When an error occurs (both client and server, 4XX and 5XX status-codes) the response body contains an object describing the error that occurred. An example for a 404-status when a task is not found:

    {
      "statusCode" : 404,
      "errorMessage" : "Could not find a task with id '444'."
    }

### Request parameters

#### URL fragments

Parameters that are part of the URL (for example, the deploymentId parameter in http://host/flowable-rest/event-registry-api/event-registry-repository/deployments/{deploymentId})
need to be properly escaped (see [URL-encoding or Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding)) in case the segment contains special characters. Most frameworks have this functionality built in, but it should be taken into account. Especially for segments that can contain forward-slashes (for example, deployment resource), this is required.

#### Rest URL query parameters

Parameters added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/event-registry-api/event-registry-repository/deployments?name=Deployment) can have the following types and are mentioned in the corresponding REST-API documentation:

<table>
<caption>URL query parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. Can contain any valid characters that are allowed in URLs. In the case of a XXXLike parameter, the string should contain the wildcard character % (properly URL-encoded). This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Boolean</p></td>
<td><p>Parameter representing a boolean value. Can be either true or false. All other values other than these will cause a '405 - Bad request' response.</p></td>
</tr>
<tr class="odd">
<td><p>Date</p></td>
<td><p>Parameter representing a date value. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (e.g. 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### JSON body parameters

<table>
<caption>JSON parameter types</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Type</th>
<th>Format</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>String</p></td>
<td><p>Plain text parameters. In the case of a XXXLike parameter, the string should contain the wildcard character %. This allows you to specify the intent of the like-search. For example, 'Tas%' matches all values, starting with 'Tas'.</p></td>
</tr>
<tr class="even">
<td><p>Integer</p></td>
<td><p>Parameter representing an integer value, using a JSON number. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.</p></td>
</tr>
<tr class="odd">
<td><p>Long</p></td>
<td><p>Parameter representing a long value, using a JSON number. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.</p></td>
</tr>
<tr class="even">
<td><p>Date</p></td>
<td><p>Parameter representing a date value, using a JSON text. Use the ISO-8601 date-format (see <a href="http://en.wikipedia.org/wiki/ISO_8601">ISO-8601 on wikipedia</a>) using both time and date-components (for example, 2013-04-03T23:45Z).</p></td>
</tr>
</tbody>
</table>

#### Paging and sorting

Paging and order parameters can be added as query-string in the URL (for example, the name parameter used in http://host/flowable-rest/event-registry-api/event-registry-repository/deployments?sort=name).

<table>
<caption>Variable query JSON parameters</caption>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>sort</p></td>
<td><p>different per query implementation</p></td>
<td><p>Name of the sort key, for which the default value and the allowed values are different per query implementation.</p></td>
</tr>
<tr class="even">
<td><p>order</p></td>
<td><p>asc</p></td>
<td><p>Sorting order which can be 'asc' or 'desc'.</p></td>
</tr>
<tr class="odd">
<td><p>start</p></td>
<td><p>0</p></td>
<td><p>Parameter to allow for paging of the result. By default the result will start at 0.</p></td>
</tr>
<tr class="even">
<td><p>size</p></td>
<td><p>10</p></td>
<td><p>Parameter to allow for paging of the result. By default the size will be 10.</p></td>
</tr>
</tbody>
</table>

> **Note**
>
> Bear in mind that the start parameter is used as the offset of the query. For example, to get tasks in three pages of three items each (9 items), we would use:
>
>     GET /runtime/tasks?start=0&size=3
>     GET /runtime/tasks?start=3&size=3
>     GET /runtime/tasks?start=6&size=3

## Deployment

**When using Tomcat, please read [Usage in Tomcat](#usage-in-tomcat).**

### List of Event Registry Deployments

    GET event-registry-repository/deployments

<table>
<caption>URL query parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given name.</p></td>
</tr>
<tr class="even">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a name like the given name.</p></td>
</tr>
<tr class="odd">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given category.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>parentDeploymentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given parent deployment id.</p></td>
</tr>
<tr class="even">
<td><p>parentDeploymentIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a parent deployment id like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>tenantId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with the given tenantId.</p></td>
</tr>
<tr class="even">
<td><p>tenantIdLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return deployments with a tenantId like the given value.</p></td>
</tr>
<tr class="odd">
<td><p>withoutTenantId</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>If true, only returns deployments without a tenantId set. If false, the withoutTenantId parameter is ignored.</p></td>
</tr>
<tr class="even">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'id' (default), 'name', 'deploytime' or 'tenantId'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>REST Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the request was successful.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
        {
          "id": "03ab310d-c1de-11e6-a4f4-62ce84ef239e",
          "name": null,
          "deploymentTime": "2016-12-14T10:16:37.000+01:00",
          "category": null,
          "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/deployments/03ab310d-c1de-11e6-a4f4-62ce84ef239e",
          "parentDeploymentId": "17510",
          "tenantId": ""
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "id",
      "order": "asc",
      "size": 1
    }

### Get an Event Registry deployment

    GET event-registry-repository/deployments/{deploymentId}

<table>
<caption>Get a deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the deployment to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the deployment was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "name": null,
      "deploymentTime": "2016-12-14T10:16:37.000+01:00",
      "category": null,
      "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/deployments/03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "parentDeploymentId": "17510",
      "tenantId": ""
    }

### Create a new Event Registry deployment

    POST event-registry-repository/deployments

**Request body:**

The request body should contain data of type *multipart/form-data*. There should be exactly one file in the request: any additional files will be ignored. The deployment name is the name of the file-field passed in.

An additional parameter (form-field) can be passed in the request body with name tenantId. The value of this field will be used as the identifier of the tenant in which this deployment is done.

<table>
<caption>Create a new Event deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the deployment was created.</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates there was no content present in the request body or the content mime-type is not supported for deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "name": "newDeployment1",
      "deploymentTime": "2016-12-14T10:16:37.000+01:00",
      "category": null,
      "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/deployments/03ab310d-c1de-11e6-a4f4-62ce84ef239e",
      "parentDeploymentId": "17510",
      "tenantId" : "myTenant"
    }

### Delete an Event Registry deployment

    DELETE event-registry-repository/deployments/{deploymentId}

<table>
<caption>Delete an Event Registry deployment - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the deployment to delete.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Delete an Event Registry deployment - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>204</p></td>
<td><p>Indicates the deployment was found and has been deleted. Response-body is intentionally empty.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found.</p></td>
</tr>
</tbody>
</table>

### Get an Event Registry deployment resource content

    GET event-registry-repository/deployments/{deploymentId}/resourcedata/{resourceId}

<table>
<caption>Get a deployment resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the deployment the requested resource is part of.</p></td>
</tr>
<tr class="even">
<td><p>resourceId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the resource to get the data for. <strong>Make sure you URL-encode the resourceId in case it contains forward slashes. For example, use 'events%2Fmy-event.event' instead of 'events/my-event.event'.</strong></p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a deployment resource content - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates both deployment and resource have been found and the resource data has been returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested deployment was not found or there is no resource with the given identifier present in the deployment. The status-description contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

The response body will contain the binary resource-content for the requested resource. The response content-type will be the same as the type returned in the resources 'mimeType' property. Also, a content-disposition header is set, allowing browsers to download the file instead of displaying it.

## Event Definitions

### List of event definitions

    GET event-registry-repository/event-definitions

<table>
<caption>List of event definitions - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>version</p></td>
<td><p>No</p></td>
<td><p>integer</p></td>
<td><p>Only return event definitions with the given version.</p></td>
</tr>
<tr class="even">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with the given name.</p></td>
</tr>
<tr class="odd">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with a name like the given name.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with the given key.</p></td>
</tr>
<tr class="odd">
<td><p>keyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with a key like the given key.</p></td>
</tr>
<tr class="even">
<td><p>resourceName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with the given resource name.</p></td>
</tr>
<tr class="odd">
<td><p>resourceNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with a name like the given resource name.</p></td>
</tr>
<tr class="even">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with the given category.</p></td>
</tr>
<tr class="odd">
<td><p>categoryLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions with a category like the given name.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return event definitions which are part of a deployment with the given identifier.</p></td>
</tr>
<tr class="even">
<td><p>latest</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Only return the latest event definition versions. Can only be used together with 'key' and 'keyLike' parameters, using any other parameter will result in a 400-response.</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'name' (default), 'id', 'key', 'category', 'deploymentId' and 'tenantId'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of event definitions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the event definitions are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format or that 'latest' is used with other parameters other than 'key' and 'keyLike'. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
            {
          "id": "46b0379c-c0a1-11e6-bc93-6ab56fad108a",
          "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/event-definitions/46b0379c-c0a1-11e6-bc93-6ab56fad108a",
          "category": null,
          "name": "Event Definition One",
          "key": "EventDefinitionOne",
          "description": null,
          "version": 3,
          "resourceName": "EventDefinitionOne.event",
          "deploymentId": "46aa6b3a-c0a1-11e6-bc93-6ab56fad108a",
          "parentDeploymentId": "5001",
          "tenantId": ""
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Get an event definition

    GET event-registry-repository/event-definitions/{eventDefinitionId}

<table>
<caption>Get an event definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>eventDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the event definition to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get an event definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the event definition was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested event definition was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "46b0379c-c0a1-11e6-bc93-6ab56fad108a",
      "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/event-definitions/46b0379c-c0a1-11e6-bc93-6ab56fad108a",
      "category": null,
      "name": "Event Definition One",
      "key": "EventDefinitionOne",
      "description": null,
      "version": 3,
      "resourceName": "EventDefinitionOne.event",
      "deploymentId": "46aa6b3a-c0a1-11e6-bc93-6ab56fad108a",
      "parentDeploymentId": "5001",
      "tenantId": ""
    }

### Get an event definition resource content

    GET event-registry-repository/event-definitions/{eventDefinitionId}/resourcedata

<table>
<caption>Get an event definition resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>eventDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the event definition to get the resource data for.</p></td>
</tr>
</tbody>
</table>

**Response:**

Exactly the same response codes as GET event-registry-repository/deployments/{deploymentId}/resourcedata/{resourceId}.

### Get an event definition model

    GET event-registry-repository/event-definitions/{eventDefinitionId}/model

<table>
<caption>Get an event definition model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>eventDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the event definition to get the model for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get an event definition model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the event definition was found and the model is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested event definition was not found.</p></td>
</tr>
</tbody>
</table>

**Response body:**
The response body is a JSON representation of the org.flowable.eventregistry.model.EventModel.

    {
       "key": "myEvent",
       "name": "My event",
       "correlationParameters": [
          {
            "name": "customerId",
            "type": "string"
          }
       ],
       "payload": [
          {
            "name": "payload1",
            "type": "string"
          },
          {
            "name": "payload2",
            "type": "integer"
          }
       ]
    }
    
## Channel Definitions

### List of channel definitions

    GET event-registry-repository/channel-definitions

<table>
<caption>List of channel definitions - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>version</p></td>
<td><p>No</p></td>
<td><p>integer</p></td>
<td><p>Only return channel definitions with the given version.</p></td>
</tr>
<tr class="even">
<td><p>name</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with the given name.</p></td>
</tr>
<tr class="odd">
<td><p>nameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with a name like the given name.</p></td>
</tr>
<tr class="even">
<td><p>key</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with the given key.</p></td>
</tr>
<tr class="odd">
<td><p>keyLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with a key like the given key.</p></td>
</tr>
<tr class="even">
<td><p>resourceName</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with the given resource name.</p></td>
</tr>
<tr class="odd">
<td><p>resourceNameLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with a name like the given resource name.</p></td>
</tr>
<tr class="even">
<td><p>category</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with the given category.</p></td>
</tr>
<tr class="odd">
<td><p>categoryLike</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions with a category like the given name.</p></td>
</tr>
<tr class="even">
<td><p>categoryNotEquals</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions which don’t have the given category.</p></td>
</tr>
<tr class="odd">
<td><p>deploymentId</p></td>
<td><p>No</p></td>
<td><p>String</p></td>
<td><p>Only return channel definitions which are part of a deployment with the given identifier.</p></td>
</tr>
<tr class="even">
<td><p>latest</p></td>
<td><p>No</p></td>
<td><p>Boolean</p></td>
<td><p>Only return the latest channel definition versions. Can only be used together with 'key' and 'keyLike' parameters, using any other parameter will result in a 400-response.</p></td>
</tr>
<tr class="odd">
<td><p>sort</p></td>
<td><p>No</p></td>
<td><p>'name' (default), 'id', 'key', 'category', 'deploymentId' and 'tenantId'</p></td>
<td><p>Property to sort on, to be used together with the 'order'.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>List of channel definitions - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates request was successful and the channel definitions are returned</p></td>
</tr>
<tr class="even">
<td><p>400</p></td>
<td><p>Indicates a parameter was passed in the wrong format or that 'latest' is used with other parameters other than 'key' and 'keyLike'. The status-message contains additional information.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "data": [
            {
          "id": "46b0379c-c0a1-11e6-bc93-6ab56fad108a",
          "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/channel-definitions/46b0379c-c0a1-11e6-bc93-6ab56fad108a",
          "category": null,
          "name": "Channel Definition One",
          "key": "ChannelDefinitionOne",
          "description": null,
          "version": 3,
          "resourceName": "ChannelDefinitionOne.channel",
          "deploymentId": "46aa6b3a-c0a1-11e6-bc93-6ab56fad108a",
          "parentDeploymentId": "5001",
          "tenantId": ""
        }
      ],
      "total": 1,
      "start": 0,
      "sort": "name",
      "order": "asc",
      "size": 1
    }

### Get a channel definition

    GET event-registry-repository/channel-definitions/{channelDefinitionId}

<table>
<caption>Get a channel definition - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>channelDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the channel definition to get.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a channel definition - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the channel definition was found and returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested channel definition was not found.</p></td>
</tr>
</tbody>
</table>

**Success response body:**

    {
      "id": "46b0379c-c0a1-11e6-bc93-6ab56fad108a",
      "url": "http://localhost:8080/flowable-rest/event-registry-api/event-registry-repository/channel-definitions/46b0379c-c0a1-11e6-bc93-6ab56fad108a",
      "category": null,
      "name": "Channel Definition One",
      "key": "ChannelDefinitionOne",
      "description": null,
      "version": 3,
      "resourceName": "ChannelDefinitionOne.channel",
      "deploymentId": "46aa6b3a-c0a1-11e6-bc93-6ab56fad108a",
      "parentDeploymentId": "5001",
      "tenantId": ""
    }

### Get a channel definition resource content

    GET event-registry-repository/channel-definitions/{channelDefinitionId}/resourcedata

<table>
<caption>Get a channel definition resource content - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>channelDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the channel definition to get the resource data for.</p></td>
</tr>
</tbody>
</table>

**Response:**

Exactly the same response codes as GET event-registry-repository/deployments/{deploymentId}/resourcedata/{resourceId}.

### Get a channel definition model

    GET event-registry-repository/channel-definitions/{channelDefinitionId}/model

<table>
<caption>Get a channel definition model - URL parameters</caption>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>Parameter</th>
<th>Required</th>
<th>Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>channelDefinitionId</p></td>
<td><p>Yes</p></td>
<td><p>String</p></td>
<td><p>The identifier of the channel definition to get the model for.</p></td>
</tr>
</tbody>
</table>

<table>
<caption>Get a channel definition model - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the channel definition was found and the model is returned.</p></td>
</tr>
<tr class="even">
<td><p>404</p></td>
<td><p>Indicates the requested channel definition was not found.</p></td>
</tr>
</tbody>
</table>

**Response body:**
The response body is a JSON representation of the org.flowable.eventregistry.model.ChannelModel.

    {
       "key": "myChannel",
       "category": "channel",
       "name": "My channel",
       "description": "My channel description",
       "channelType": "inbound",
       "type": "jms",
       "destination": "testQueue",
       "deserializerType": "json",
       "channelEventKeyDetection": {
          "fixedValue": "myEvent"
       }
    }

## Event Registry Service

### Send an event

    POST event-registry-runtime/event-instances

**Request body:**

   {
      "eventDefinitionKey": "myEvent",
      "eventPayload": {
          "customerName": "John Doe",
          "productName": "Laptop"
      },
      "tenantId": "tenant1"
   }
   
Instead of an event definition key it's also possible to use an event definition id.   

There's no response body when sending an event.

<table>
<caption>Send an event - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>201</p></td>
<td><p>Indicates the event has been sent.</p></td>
</tr>
</tbody>
</table>

## Engine

### Get Event Registry engine info

    GET event-registry-management/engine

Returns a read-only view of the Event Registry engine that is used in this REST-service.

**Success response body:**

    {
       "name":"default",
       "version":"6.6.0"
    }

<table>
<caption>Get engine information - Response codes</caption>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr class="header">
<th>Response code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><p>200</p></td>
<td><p>Indicates the engine information has been returned.</p></td>
</tr>
</tbody>
</table>

---

### Public Api Tools Flowable Slate Templates  Rest Title (`docs/public-api/tools/flowable-slate/templates/_rest-title.md`)

# Flowable API_NAME REST API v1

> Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

---

### Public Api Tools Flowable Slate Slate Source Index.Html (`docs/public-api/tools/flowable-slate/slate/source/index.html.md`)

---
title: Flowable Form REST API v1
language_tabs:
  - shell: Shell
  - http: HTTP
  - javascript: JavaScript
  - javascript--nodejs: Node.JS
  - ruby: Ruby
  - python: Python
  - java: Java
toc_footers: []
includes:
  - rest-title.md
  - rest-header.md
  - rest-body.md
  - rest-footer.md
search: true
highlight_theme: darkula
headingLevel: 2
---

---

### Public Api Tools Flowable Slate Slate Source Includes  Errors (`docs/public-api/tools/flowable-slate/slate/source/includes/_errors.md`)

# Errors

<aside class="notice">This error section is stored in a separate file in `includes/_errors.md`. Slate allows you to optionally separate out your docs into many files...just save them to the `includes` folder and add them to the top of your `index.md`'s frontmatter. Files are included in the order listed.</aside>

The Kittn API uses the following error codes:


Error Code | Meaning
---------- | -------
400 | Bad Request -- Your request sucks.
401 | Unauthorized -- Your API key is wrong.
403 | Forbidden -- The kitten requested is hidden for administrators only.
404 | Not Found -- The specified kitten could not be found.
405 | Method Not Allowed -- You tried to access a kitten with an invalid method.
406 | Not Acceptable -- You requested a format that isn't json.
410 | Gone -- The kitten requested has been removed from our servers.
418 | I'm a teapot.
429 | Too Many Requests -- You're requesting too many kittens! Slow down!
500 | Internal Server Error -- We had a problem with our server. Try again later.
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

---

### Public Api Tools Flowable Slate Slate Source Includes  Rest Footer (`docs/public-api/tools/flowable-slate/slate/source/includes/_rest-footer.md`)

# Flowable Links

| Title | Type | Description |
| :------------ | :---------------:| :-----|
| [Flowable Website](http://www.flowable.org/) | Website | The official Flowable website. Your primary reference for everything |
| [Flowable Source Code](https://github.com/flowable/flowable-engine) | Github | The official Flowable Github repository. This is where the source code is.|
| [Flowable Docs ](http://www.flowable.org/documentation.html) | Website | The official Flowable Docs. Use this to learn Flowable |
| [Flowable Enterprise Support](https://www.edorasware.com/flowable-core/) | Website | The official Flowable Enterprise Support. |
| [Flowable Forums](https://forum.flowable.org/) | Forums | The Flowable Forums where you can ask any questions.|

---

### Public Api Tools Flowable Slate Slate Source Includes  Rest Header (`docs/public-api/tools/flowable-slate/slate/source/includes/_rest-header.md`)

# Flowable REST principles

## Installation and Authentication

Flowable includes a REST API to the Flowable engine that can be installed by deploying the flowable-rest.war file to a servlet container like Apache Tomcat. However, it can also be used in another web-application by including the servlet and its mapping in your application and add all flowable-rest dependencies to the classpath.

By default the Flowable engine will connect to an in-memory H2 database. You can change the database settings in the db.properties file in the WEB-INF/classes folder. The REST API uses JSON format (http://www.json.org) and is built upon the Spring MVC (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html).

All REST-resources require a valid Flowable-user to be authenticated by default. Basic HTTP access authentication is used, so you should always include a _Authorization: Basic ...==_ HTTP-header when performing requests or include the username and password in the request-url (for example, _http://username:password@localhost:8080/xyz_).

*We recommend that you use Basic Authentication in combination with HTTPS.*

## Configuration

The Flowable REST web application uses Spring Java Configuration for starting the Flowable Form engine, defining the basic authentication security using Spring security, and to define the variable converters for specific variable handling.
A small number of properties can be defined by changing the engine.properties file you can find in the WEB-INF/classes folder.
If you need more advanced configuration options there's the possibility to override the default Spring beans in XML in the flowable-custom-context.xml file you can also find in the WEB-INF/classes folder.
An example configuration is already in comments in this file. This is also the place to override the default RestResponseFactory by defining a new Spring bean with the name restResponsefactory and use your custom implementation class for it.

## Usage in Tomcat

Due to [default security properties on Tomcat](http://tomcat.apache.org/tomcat-8.0-doc/security-howto.html), **escaped forward slashes (%2F and %5C) are not allowed by default (400-result is returned).** This may have an impact on the deployment resources and their data-URL, as the URL can potentially contain escaped forward slashes.

When issues are experienced with unexpected 400-results, set the following system-property:

_-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true_

It's best practice to always set the *Accept* and *Content-Type* (in case of posting/putting JSON) headers to *application/json* on the HTTP requests described below.

## Methods and return-codes

### HTTP-methods and corresponding operations

|Method|Operations
------ | ---------
|**GET**|Get a single resource or get a collection of resources.
|**POST**|Create a new resource. Also used for executing resource-queries which have a too complex request-structure to fit in the query-URL of a GET-request.
|**PUT**|Update properties of an existing resource. Also used for invoking actions on an existing resource.
|**DELETE**|Delete an existing resource.


### HTTP-methods response codes


|Response|Description
-------- | ----------
|**200 - Ok**|The operation was successful and a response has been returned (**GET** and **PUT** requests).
|**201 - Created**|The operation was successful and the entity has been created and is returned in the response-body (**POST** request).
|**204 - No content**|The operation was successful and entity has been deleted and therefore there is no response-body returned (**DELETE** request).
|**401 - Unauthorized**|The operation failed. The operation requires an Authentication header to be set. If this was present in the request, the supplied credentials are not valid or the user is not authorized to perform this operation.
|**403 - Forbidden**|The operation is forbidden and should not be re-attempted. This implies an issue with authorization not authentication, it's an operation that is not allowed. Example: deleting a task that is part of a running process is not allowed and will never be allowed, regardless of the user or process/task state.
|**404 - Not found**|The operation failed. The requested resource was not found.
|**405 - Method not allowed**|The operation failed. The method is not allowed for this resource. For example, trying to update (PUT) a deployment-resource will result in a **405** status.
|**409 - Conflict**|The operation failed. The operation causes an update of a resource that has been updated by another operation, which makes the update no longer valid. Can also indicate a resource that is being created in a collection where a resource with that identifier already exists.
|**415 - Unsupported Media Type**|The operation failed. The request body contains an unsupported media type. Also occurs when the request-body JSON contains an unknown attribute or value that doesn't have the right format/type to be accepted.
|**500 - Internal server error**|The operation failed. An unexpected exception occurred while executing the operation. The response-body contains details about the error.


The media-type of the HTTP-responses is always **application/json** unless binary content is requested (for example, deployment resource data), the media-type of the content is used.

## Error response body

When an error occurs (both client and server, 4XX and 5XX status-codes) the response body contains an object describing the error that occurred. An example for a 404-status when a task is not found:

```json
{
  "statusCode" : 404,
  "errorMessage" : "Could not find a task with id '444'."
}
```

## Request parameters

### URL fragments

Parameters that are part of the URL (for example, the deploymentId parameter in *http://host/flowable-rest/process-api/repository/deployments/{deploymentId}*) need to be properly escaped (see link [URL-encoding or Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding)) in case the segment contains special characters. Most frameworks have this functionality built in, but it should be taken into account. Especially for segments that can contain forward-slashes (for example, deployment resource), this is required.


### Rest URL query parameters

Parameters added as query-string in the URL (for example, the name parameter used in *http://host/flowable-rest/process-api/repository/deployments?name=Deployment*) can have the following types and are mentioned in the corresponding REST-API documentation:


|Type|Format
---- | -----
|String|Plain text parameters. Can contain any valid characters that are allowed in URLs. In the case of a *XXXLike* parameter, the string should contain the wildcard character **%** (properly URL-encoded). This allows you to specify the intent of the like-search. For example, '*Tas%*' matches all values, starting with 'Tas'.
|Integer|Parameter representing an integer value. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.
|Long|Parameter representing a long value. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.
|Boolean|Parameter representing a boolean value. Can be either *true* or *false*. All other values other than these will cause a '**405 - Bad request**' response.
|Date|Parameter representing a date value. Use the ISO-8601 date-format (see [ISO-8601 on wikipedia](http://en.wikipedia.org/wiki/ISO_8601) using both time and date-components (e.g. *2013-04-03T23:45:12Z*).


### JSON body parameters

|Type|Format
---- | -----
|String|Plain text parameters. In the case of a *XXXLike* parameter, the string should contain the wildcard character *%*. This allows you to specify the intent of the like-search. For example, '*Tas%*' matches all values, starting with 'Tas'.
|Integer|Parameter representing an integer value, using a JSON number. Can only contain numeric non-decimal values, between -2.147.483.648 and 2.147.483.647.
|Long|Parameter representing a long value, using a JSON number. Can only contain numeric non-decimal values, between -9.223.372.036.854.775.808 and 9.223.372.036.854.775.807.
|Date|Parameter representing a date value, using a JSON text. Use the ISO-8601 date-format (see [ISO-8601 on wikipedia](http://en.wikipedia.org/wiki/ISO_8601) using both time and date-components (for example, *2013-04-03T23:45Z*).



### Paging and sorting

Paging and order parameters can be added as query-string in the URL (for example, the name parameter used in *http://host/flowable-rest/process-api/repository/deployments?sort=name*).


|Parameter|Default value|Description
--------- | ----------- | ----------
|sort|different per query implementation|Name of the sort key, for which the default value and the allowed values are different per query implementation.
|order|asc|Sorting order which can be 'asc' or 'desc'.
|start|0|Parameter to allow for paging of the result. By default the result will start at 0.
|size|10|Parameter to allow for paging of the result. By default the size will be 10.


### JSON query variable format

```json
{
  "name" : "variableName",
  "value" : "variableValue",
  "operation" : "equals",
  "type" : "string"
}
```


### Variable query JSON parameters

|Parameter|Required|Description
--------- | ------ | ----------
|name|No|Name of the variable to include in a query. Can be empty in the case where '*equals*' is used in some queries to query for resources that have *any variable name* with the given value.
|value|Yes|Value of the variable included in the query, should include a correct format for the given type.
|operator|Yes|Operator to use in query, can have the following values: **equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, lessThan, greaterThan, lessThanOrEquals, greaterThanOrEquals** and **like**.
|type|No|Type of variable to use. When omitted, the type will be deduced from the **value** parameter. Any JSON text-values will be considered of type **string**, JSON booleans of type **boolean**, JSON numbers of type **long** or **integer** depending on the size of the number. We recommended you include an explicit type when in doubt. Types supported out of the box are listed below.



### Default query JSON types

|Type name|Description
--------- | ----------
|string|Value is treated as and converted to a **java.lang.String**.
|short|Value is treated as and converted to a **java.lang.Integer**.
|integer|Value is treated as and converted to a **java.lang.Integer**.
|long|Value is treated as and converted to a **java.lang.Long**.
|double|Value is treated as and converted to a **java.lang.Double**.
|boolean|Value is treated as and converted to a **java.lang.Boolean**.
|date|Value is treated as and converted to a **java.util.Date**. The JSON string will be converted using ISO-8601 date format.


### Variable representation

When working with variables (execute decision), the REST API uses some common principles and JSON-format for both reading and writing. The JSON representation of a variable looks like this:

```json
{
  "name" : "variableName",
  "value" : "variableValue",
  "valueUrl" : "http://...",
  "type" : "string"
}
```

### Variable JSON attributes

|Parameter|Required|Description
--------- | ------ | ----------
|name|Yes|Name of the variable.
|value|No|Value of the variable. When writing a variable and **value** is omitted, **null** will be used as value.
|valueUrl|No|When reading a variable of type **binary** or **serializable**, this attribute will point to the URL from where the raw binary data can be fetched.
|type|No|Type of the variable. See table below for additional information on types. When writing a variable and this value is omitted, the type will be deduced from the raw JSON-attribute request type and is limited to either **string**, **double**, **integer** and **boolean**. We advise you to always include a type to make sure no wrong assumption about the type are made.



### Variable Types

|Type name|Description
--------- | ----------
|string|Value is treated as a **java.lang.String**. Raw JSON-text value is used when writing a variable.
|integer|Value is treated as a **java.lang.Integer**. When writing, JSON number value is used as base for conversion, falls back to JSON text.
|short|Value is treated as a **java.lang.Short**. When writing, JSON number value is used as base for conversion, falls back to JSON text.
|long|Value is treated as a **java.lang.Long**. When writing, JSON number value is used as base for conversion, falls back to JSON text.
|double|Value is treated as a **java.lang.Double**. When writing, JSON number value is used as base for conversion, falls back to JSON text.
|boolean|Value is treated as a **java.lang.Boolean**. When writing, JSON boolean value is used for conversion.
|date|Value is treated as a **java.util.Date**. When writing, the JSON text will be converted using ISO-8601 date format.


It's possible to support additional variable-types with a custom JSON representation (either simple value or complex/nested JSON object). By extending the **initializeVariableConverters()** method on *org.flowable.dmn.rest.service.api.DmnRestResponseFactory**, you can add additional **org.flowable.rest.variable.RestVariableConverter* classes to support converting your POJOs to a format suitable for transferring through REST and converting the REST-value back to your POJO. The actual transformation to JSON is done by Jackson.

---

### Modules Flowable App Rest Src Main Resources Static Docs Readme (`modules/flowable-app-rest/src/main/resources/static/docs/readme.txt`)

Steps to upgrade:

* Remove content of docs folder
* Download latest release from https://github.com/swagger-api/swagger-ui
* Unzip + copy dist folder contents to docs folder
* Edit index.html and update javascript to contain "url = "specfile/flowable.json";"
* Edit index.html to change to swagger-ui.min.js instead of non-minified version.

---

### Public Api Tools Flowable Oas Generator Src Main Resources Swagger Info (`docs/public-api/tools/flowable-oas-generator/src/main/resources/swagger/info.txt`)

# flowable / flowəb(ə)l /

- a compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.
- a lightning fast, tried and tested BPMN 2 process engine written in Java. It is Apache 2.0 licensed open source, with a committed community.
- can run embedded in a Java application, or as a service on a server, a cluster, and in the cloud. It integrates perfectly with Spring. With a rich Java and REST API, it is the ideal engine for orchestrating human or system activities.

---

--- METRICS ---
- Files Extracted: 59
- Estimated Token Budget: ~363877 tokens
- Canonical Reference: https://codewiki.google/github.com/flowable/flowable-engine
