1. Introduction

1.1. License

Flowable is distributed under the Apache V2 license.

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

1.4. Required software

1.4.1. JDK 7+

Flowable runs on a JDK higher than or equal to version 7. Go to Oracle Java SE downloads 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.

1.4.2. IDE

Flowable development can be done with the IDE of your choice. If you would like to use the Flowable Designer then you need Eclipse Mars or Neon. Download the Eclipse distribution of your choice from the Eclipse download page. Unzip the downloaded file and then you should be able to start it with the eclipse file in the directory eclipse. Further in this user guide, there is a section on installing our eclipse designer plugin.

1.5. Reporting problems

We expect developers to have have read How to ask questions the smart way.

After you’ve done that you can post questions and comments on the Users forum and create issues in our Github issue tracker.

1.6. 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. However, if the user guide mentions those classes as configuration values, they are supported and can be considered stable.

1.7. Internal implementation classes

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

2. Configuration

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

The easiest way to obtain a DmnEngine, is to use the org.flowable.dmn.engine.DmnEngines class:

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<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" /> </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).

1 2 3 4 5 6
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 for more information).

1 2
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:

1 2 3 4
DmnEngine dmnEngine = DmnEngineConfiguration.createStandaloneInMemDmnEngineConfiguration() .setDatabaseSchemaUpdate(DmnEngineConfiguration.DB_SCHEMA_UPDATE_FALSE) .setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000") .buildDmnEngine();

2.2. DmnEngineConfiguration bean

The flowable.dmn.cfg.xml must contain a bean that has the ID 'dmnEngineConfiguration'.

1
<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 for more information.

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
<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>

2.4. 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 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:

1 2 3 4
<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 DBCP, C3P0, Hikari, Tomcat Connection Pool, and so on) and inject it into the process engine configuration :

1 2 3 4 5 6 7 8 9 10 11 12
<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 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.

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

2.5.1. 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:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<?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>

2.5.2. JNDI properties

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

  • 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".

2.6. Supported databases

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

Flowable DMN database type Example JDBC URL Notes

h2

jdbc:h2:tcp://localhost/flowable_dmn

Default configured database

mysql

jdbc:mysql://localhost:3306/flowable_dmn?autoReconnect=true

Tested using mysql-connector-java database driver

oracle

jdbc:oracle:thin:@localhost:1521:xe

postgres

jdbc:postgresql://localhost:5432/flowable_dmn

db2

jdbc:db2://localhost:50000/flowable_dmn

mssql

jdbc:sqlserver://localhost:1433;databaseName=flowable_dmn (jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver) OR jdbc:jtds:sqlserver://localhost:1433/flowable_dmn (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)

Tested using Microsoft JDBC Driver 4.0 (sqljdbc4.jar) and JTDS Driver

2.7. Creating the database tables

Flowable DMM uses Liquibase 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)

  • Execute the main method of the DbSchemaCreate class

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

2.9. 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:

1 2 3 4 5 6 7 8 9
<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.

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

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

1 2 3
<property name="decisionCache"> <bean class="org.flowable.MyCache" /> </property>

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

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

1 2 3 4
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>

The flowable-ui and flowable-rest webapps are 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). If your container provides a commons-logging implementation, please follow directions on this page: http://www.slf4j.org/codes.html#release to ensure stability.

Example when using Maven (version omitted):

1 2 3 4
<dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> </dependency>

3. The Flowable DMN API

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

1 2 3 4
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 <dmn-introduction, DMN introduction section>). 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.

3.2. 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 the javadocs. For example, an extract from DmnRuleService:

1 2 3 4 5 6 7 8 9 10 11 12
/** * 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 FlowableExceptionss.

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

3.3. 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:

1 2 3 4
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.

1 2 3 4 5 6 7
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();

3.4. 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 version 4 style of unit testing. When writing JUnit 4 unit tests, the org.flowable.dmn.engine.test.FlowableDmnRule Rule can be used. Through this rule, the DMN engine and services are available through getters. Including this Rule will enable the use of the org.flowable.dmn.engine.test.DmnDeploymentAnnotation annotation (see above for an explanation of its use and configuration) and it will look for the default configuration file on the classpath. DMN engines are statically cached over multiple unit tests when using the same configuration resource. It’s also possible to provide a custom engine configuration to the rule.

The following code snippet shows an example of using the JUnit 4 style of testing and the usage of the FlowableDmnRule (and passing an optional custom configuration):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class MyDecisionTableTest { @Rule public FlowableDmnRule flowableDmnRule = new FlowableDmnRule("custom1.flowable.dmn.cfg.xml"); @Test @DmnDeploymentAnnotation public void ruleUsageExample() { DmnEngine dmnEngine = flowableDmnRule.getDmnEngine(); DmnRuleService dmnRuleService = dmnEngine.getDmnRuleService(); Map<String, Object> inputVariables = new HashMap<>(); inputVariables.put("inputVariable1", 2); inputVariables.put("inputVariable2", "test2"); RuleEngineExecutionResult result = dmnRuleService.executeDecisionByKey("decision1", inputVariables); Assert.assertEquals("result2", result.getResultVariables().get("outputVariable1")); } }

3.5. 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:

1 2 3 4 5 6 7 8 9 10 11
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:

1
DmnEngines.getDefaultDmnEngine()

or:

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

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

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

4.1. 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. For Spring integration, the configuration and engine beans will look like this:

1 2 3 4 5 6 7
<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.

4.2. 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:

1 2 3 4 5 6 7 8 9
<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:

1 2 3 4 5 6
<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.

4.3. Unit testing

When integrating with Spring, decisions can be tested very easily using the standard Flowable testing facilities. The following example shows how a decision is tested in a typical Spring-based unit test:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:org/flowable/spring/test/junit4/springTypicalUsageTest-context.xml") public class SpringJunit4Test { @Autowired private DmnEngine dmnEngine; @Autowired private DmnRuleService ruleService; @Autowired @Rule public FlowableDmnRule flowableSpringRule; @Test @DmnDeploymentAnnotation public void simpleDecisionTest() { Map<String, Object> inputVariables = new HashMap<>(); inputVariables.put("input1", "testString"); RuleEngineExecutionResult executionResult = ruleService.executeDecisionByKey("decision1", inputVariables); assertEquals("test1", executionResult.getResultVariables().get("output1")); } }

Note that for this to work, you need to define an org.flowable.dmn.engine.test.FlowableDmnRule bean in the Spring configuration (which is injected by auto-wiring in the example above).

1 2 3
<bean id="flowableDmnRule" class="org.flowable.dmn.engine.test.FlowableDmnRule"> <property name="dmnEngine" ref="dmnEngine"/> </bean>

5. Deployment

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

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.

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

5.1.2. Deploying programmatically

Deploying a DMN definition can be done like this:

1 2 3 4 5 6 7
String dmnDefinition = "path/to/definition-one.dmn"; ZipInputStream inputStream = new ZipInputStream(new FileInputStream(barFileName)); repositoryService.createDeployment() .name("definition-one") .addClasspathResource(dmnDefinition) .deploy();

5.1.3. 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-ui-app or 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.

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

5.2. 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:

1 2 3 4
<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:

id key name version

e29d4126-ed4d-11e6-9e00-7282cbd6ce64

myDecision

My important decision

1

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:

id key name version

e29d4126-ed4d-11e6-9e00-7282cbd6ce64

myDecision

My important decision

1

e9c2a6c0-c085-11e6-9096-6ab56fad108a

myDecision

My important decision

2

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.

1 2 3 4
<definitions id="myNewDefinitions" > <decision id="myNewDecision" name="My important decision" > <decisionTable id="decisionTable1" hitPolicy="FIRST" > ...

The table will look like this:

id key name version

e29d4126-ed4d-11e6-9e00-7282cbd6ce64

myDecision

My important decision

1

e9c2a6c0-c085-11e6-9096-6ab56fad108a

myDecision

My important decision

2

d317d3f7-e948-11e6-9ce6-b28c070b517d

myNewDecision

My important decision

1

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.

5.3. Category

Both DMN deployments and decision tables can have user defined categories. The deployment category can be specified in the API like this:

1 2 3 4 5
dmnRepository .createDeployment() .category("yourCategory") ... .deploy();

The decision table category can be specified in the API like this:

1
dmnRepository.setDecisionTableCategory("e9c2a6c0-c085-11e6-9096-6ab56fad108a", "yourCategory");

6. DMN 1.1 Introduction

6.1. What is DMN?

Decision Model and Notation (DMN) is a standard published by the Object Management Group. It’s a standard approach for describing and modeling repeatable decisions within organizations to ensure that decision models are interchangeable across organizations.

6.2. 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 process 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.

1 2 3 4 5 6 7 8 9 10 11 12 13
<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>

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

decision tables 1

And select Create Decision Table.

decision tables 2

Provide a decision table name and a unique decision table key and select Create new decision table.

decision tables 3

You’re now ready to define your decision table. Let’s describe what is presented within the editor.

6.3.1. Hit Policy

In the top left corner you can select a hit policy.

There are 2 hit policies available; first (single pass) and any (single pass). When hit policy first is selected the execution of the decision table will stop when a rule is valid. When hit policy any is selected all valid rules will executed.

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

decision tables 4

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.

decision tables 5

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.

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

The DMN specification defines an expression language: (S)-FEEL. Currently, we do not supported this part of the specification. Within Flowable DMN, we use MVEL as the expression language.

decision tables 6

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

decision tables 7

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

decision tables 8

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.

decision tables 9

The decision table can now be saved. Provide a unique Decision Table key.

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

decision tables 10

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

6.5. DMN 1.1 XML

The full DMN 1.1 XML of the example above.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
<definitions xmlns="http://www.omg.org/spec/DMN/20151101" id="definition_052249e2-f35d-11e6-9c45-0242ac120005" name="Determine Discount" namespace="http://www.flowable.org/dmn"> <decision id="DET_DISC_1" name="Determine Discount"> <decisionTable id="decisionTable_052249e2-f35d-11e6-9c45-0242ac120005" hitPolicy="FIRST"> <input label="Customer Category"> <inputExpression id="inputExpression_5"> <text>customercat</text> </inputExpression> </input> <output id="outputExpression_6" label="Discount Percentage" name="discountperc" typeRef="number"></output> <rule> <inputEntry id="inputEntry_5_1"> <text>== "BRONZE"</text> </inputEntry> <outputEntry id="outputEntry_6_1"> <text>5</text> </outputEntry> </rule> <rule> <inputEntry id="inputEntry_5_2"> <text>== "SILVER"</text> </inputEntry> <outputEntry id="outputEntry_6_2"> <text>10</text> </outputEntry> </rule> <rule> <inputEntry id="inputEntry_5_3"> <text>== "GOLD"</text> </inputEntry> <outputEntry id="outputEntry_6_3"> <text>20</text> </outputEntry> </rule> <rule> <inputEntry id="inputEntry_5_4"> <text></text> </inputEntry> <outputEntry id="outputEntry_6_4"> <text>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. *

7. DMN REST API

7.1. General Flowable DMN REST principles

7.1.1. Installation and Authentication

Flowable DMN includes a REST API to the Flowable DMN engine that can be installed by deploying the flowable-app-rest.war (which includes all Flowable REST APIs) 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 adding all flowable-dmn-rest module dependencies to the classpath.

By default, the Flowable DMN 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 DMN 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 recommended using Basic Authentication in combination with HTTPS.

7.1.2. Configuration

The Flowable REST web application (flowable-app-rest) uses Spring Java Configuration for starting the Flowable engines, 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 commented in this file. This is also the place to override the default RestResponseFactories. For the DMN engine this can be done by defining a new Spring bean with the name dmnResponsefactory and use your custom implementation class for it.

7.1.3. Usage in Tomcat

Due to default security properties on Tomcat, 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 headers (when posting/putting JSON) to application/json on the HTTP requests described below.

7.1.4. Methods and return-codes

Table 1. 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 that 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.

Table 2. 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 the 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.

404 - Not found

The operation failed. The requested resource was not found.

405 - Method not allowed

The operation failed. The used 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 (such as deployment resource data), the media-type of the content is used.

7.1.5. 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:

1 2 3 4
{ "statusCode" : 404, "errorMessage" : "Could not find a decision table with key 'decision1'." }

7.1.6. 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) 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 (such as 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 3. URL query parameter types
Type Format

String

Plain text parameters. Can contain any valid characters that are allowed in URLs. In 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) using both time and date-components (for example, 2013-04-03T23:45Z).

JSON body parameters
Table 4. JSON parameter types
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) 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/dmn-api/dmn-repository/deployments?sort=name).

Table 5. Variable query JSON parameters
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
1 2 3 4 5 6
{ "name" : "variableName", "value" : "variableValue", "operation" : "equals", "type" : "string" }
Table 6. 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.

Table 7. 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:

1 2 3 4 5 6
{ "name" : "variableName", "value" : "variableValue", "valueUrl" : "http://...", "type" : "string" }
Table 8. 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.

Table 9. 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.rest.dmn.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.

7.2. Deployment

When using tomcat, please read Usage in Tomcat.

7.2.1. List of DMN Deployments

GET dmn-repository/deployments
Table 10. URL query parameters
Parameter Required Value Description

name

No

String

Only return deployments with the given name.

nameLike

No

String

Only return deployments with a name like the given name.

category

No

String

Only return deployments with the given category.

categoryNotEquals

No

String

Only return deployments which don’t have the given category.

tenantId

No

String

Only return deployments with the given tenantId.

tenantIdLike

No

String

Only return deployments with a tenantId like the given value.

withoutTenantId

No

Boolean

If true, only returns deployments without a tenantId set. If false, the withoutTenantId parameter is ignored.

sort

No

id (default), name, deploytime or tenantId

Property to sort on, to be used together with the order.

Table 11. REST Response codes
Response code Description

200

Indicates the request was successful.

Success response body:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
{ "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 }

7.2.2. Get a DMN deployment

GET dmn-repository/deployments/{deploymentId}
Table 12. Get a deployment - URL parameters
Parameter Required Value Description

deploymentId

Yes

String

The identifier of the deployment to get.

Table 13. Get a deployment - Response codes
Response code Description

200

Indicates the deployment was found and returned.

404

Indicates the requested deployment was not found.

Success response body:

1 2 3 4 5 6 7 8 9
{ "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": "" }

7.2.3. 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 14. Create a new DMN deployment - Response codes
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:

1 2 3 4 5 6 7 8
{ "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" }

7.2.4. Delete a DMN deployment

DELETE dmn-repository/deployments/{deploymentId}
Table 15. Delete a DMN deployment - URL parameters
Parameter Required Value Description

deploymentId

Yes

String

The identifier of the deployment to delete.

Table 16. Delete a DMN deployment - Response codes
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.

7.2.5. Get a DMN deployment resource content

GET dmn-repository/deployments/{deploymentId}/resourcedata/{resourceId}
Table 17. Get a deployment resource content - URL parameters
Parameter Required Value Description

deploymentId

Yes

String

The identifier of the deployment the requested resource is part of.

resourceId

Yes

String

The identifier of the resource to get the data for. 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.

Table 18. Get a deployment resource content - Response codes
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 identifier 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.

7.3. Decision Tables

7.3.1. List of decision tables

GET dmn-repository/decision-tables
Table 19. List of process definitions - URL parameters
Parameter Required Value Description

version

No

integer

Only return process definitions with the given version.

name

No

String

Only return process definitions with the given name.

nameLike

No

String

Only return process definitions with a name like the given name.

key

No

String

Only return process definitions with the given key.

keyLike

No

String

Only return process definitions with a name like the given key.

resourceName

No

String

Only return process definitions with the given resource name.

resourceNameLike

No

String

Only return process definitions with a name like the given resource name.

category

No

String

Only return process definitions with the given category.

categoryLike

No

String

Only return process definitions with a category like the given name.

categoryNotEquals

No

String

Only return process definitions which don’t have the given category.

deploymentId

No

String

Only return process definitions which are part of a deployment with the given identifier.

latest

No

Boolean

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.

sort

No

name (default), id, key, category, deploymentId and version

Property to sort on, to be used together with the order.

Table 20. List of process definitions - Response codes
Response code Description

200

Indicates request was successful and the decision tables 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:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
{ "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 }

7.3.2. Get a decision table

GET dmn-repository/decision-tables/{decisionTableId}
Table 21. Get a decision table - URL parameters
Parameter Required Value Description

decisionTableId

Yes

String

The identifier of the decision table to get.

Table 22. Get a decision table - Response codes
Response code Description

200

Indicates the decision table was found and returned.

404

Indicates the requested decision table was not found.

Success response body:

1 2 3 4 5 6 7 8 9 10 11 12 13
{ "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": "" }

7.3.3. Get a decision table resource content

GET dmn-repository/decision-tables/{decisionTableId}/resourcedata
Table 23. Get a decision table resource content - URL parameters
Parameter Required Value Description

decisionTableId

Yes

String

The identifier of the decision table to get the resource data for.

Response:

Exactly the same response codes/boy as GET dmn-repository/deployment/{deploymentId}/resourcedata/{resourceId}.

7.3.4. Get a decision table DMN model

GET dmn-repository/decision-tables/{decisionTableId}/model
Table 24. Get a decision table DMN model - URL parameters
Parameter Required Value Description

decisionTableId

Yes

String

The identifier of the decision table to get the model for.

Table 25. Get a decision table DMN model - Response codes
Response code Description

200

Indicates the decision table was found and the model is returned.

404

Indicates the requested decision table was not found.

Response body: The response body is a JSON representation of the org.flowable.dmn.model.DmnDefinition and contains the full DMN definition model.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{ "processes":[ { "id":"oneTaskProcess", "xmlRowNumber":7, "xmlColumnNumber":60, "extensionElements":{ }, "name":"The One Task Process", "executable":true, "documentation":"One task process description", ] }

7.4. Decision Executor

7.4.1. Execute a decision

POST dmn-rule/decision-executor

Request body:

The request body should contain data of type multipart/form-data. The decisionKey is required. The tenantId and a map of inputVariables (restVariables) are optional.

Response body:

1 2 3 4 5 6 7 8 9 10
{ "resultVariables": [ { "name": "output1", "type": "string", "value": "was option two" } ], "url": "http://localhost:8080/flowable-rest/dmn-api/rules/decision-executor" }

7.5. Engine

7.5.1. 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:

1 2 3 4 5 6
{ "name":"default", "version":"6.2.0", "resourceUrl":"file://flowable-dmn/flowable.dmn.cfg.xml", "exception":null }
Table 26. Get engine information - Response codes
Response code Description

200

Indicates the engine information has been returned.