1. 简介 Introduction

1.1. 协议 License

Flowable使用 the Apache V2 license 协议开源。

1.2. 下载 Download

1.3. 源码 Sources

Flowable的发布包里包含了大部分源码,以JAR文件方式提供。Flowable的源码也可以通过以下链接获得: https://github.com/flowable/flowable-engine

1.4. 必要的软件 Required software

1.4.1. JDK 7+

Flowable需要JDK 7或以上版本。访问 Oracle Java SE下载 点击“下载JDK”按钮。这个页面上也有安装指导。安装完成后,执行 java -version 校验安装是否成功。能看到JDK的版本信息就说明安装成功了。

1.4.2. IDE

可以自行选择用于Flowable开发的IDE。如果想要使用Flowable Designer,则需要Eclipse Mars或Neon。 到 Eclipse下载页面选择Eclipse版本并下载。解压下载的文件, 然后执行eclipse目录下的eclipse文件。手册后续有专门一章介绍如何安装我们的Eclipse Designer插件。

1.5. 反馈问题 Reporting problems

我们希望开发者在报告或提问任何问题之前,先看看提问的智慧。

看完提问的智慧,你可以在用户论坛提问、评论以及提交改进建议,也可以在我们的Github问题跟踪系统创建bug报告。

1.6. 试验性功能 Experimental features

标记[EXPERIMENTAL]的章节介绍的功能还不够稳定。

.impl.包下的类都是内部实现类,不保证任何形式的稳定。但是,在用户手册中,作为配置参数介绍的类,则是被官方支持的,可以保证稳定。

1.7. 内部实现类 Internal implementation classes

在JAR文件中,所有.impl.包下的类(比如org.flowable.engine.impl.db)都是只在内部使用。实现类中的所有类或接口都不保证稳定。

2. 配置 Configuration

2.1. 创建一个DMN引擎 Creating a DMN Engine

Flowable DMN引擎的结构与Flowable流程引擎十分相似。因此,本文档的部分内容与流程引擎的对应部分也十分相似。

Flowable DMN引擎使用一个名为flowable.dmn.cfg.xml的XML文件配置。请注意在使用Sping方式创建DMN引擎的情况下不是这样。

得到DmnEngine最简单的方法,是使用org.flowable.dmn.engine.DmnEngines类:

1
DmnEngine dmnEngine = DMNEngines.getDefaultDmnEngine()

这样会在classpath中查找flowable.dmn.cfg.xml文件,并使用这个文件中的配置创建一个引擎。下面的代码片段展示了一个配置的例子。之后的章节将详细介绍各配置参数。

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>

请注意这个配置XML实际上是一个Spring配置文件。但这并不意味着Flowable DMN只能用于Spring环境!我们只是简单利用Spring内部的解析与依赖注入功能来构造引擎。

也可以通过编程方式使用配置文件,来构造DMNEngineConfiguration对象。也可以使用不同的bean id(例如第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);

也可以不使用配置文件,基于默认创建配置(参考不同的支持类获得更多信息)。

1 2
DmnEngineConfiguration.createStandaloneDmnEngineConfiguration(); DmnEngineConfiguration.createStandaloneInMemDmnEngineConfiguration();

所有的DmnEngineConfiguration.createXXX()方法都返回DmnEngineConfiguration,并可以继续按需调整。调用buildDmnEngine()后,生成一个DmnEngine:

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

flowable.dmn.cfg.xml文件中必须包含一个id为'dmnEngineConfiguration'的bean。

1
<bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">

这个bean用于构建DmnEngine。有多个类可以用于定义dmnEngineConfiguration。这些类用于不同的环境,并各自设置一些默认值。最佳实践是选择最匹配你环境的类,以便减少配置引擎需要的参数。下面列出目前可以使用的类:

  • org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration: 流程引擎独立运行。Flowable自行处理事务。在默认情况下,数据库检查只在引擎启动时进行(如果Flowable DMN表结构不存在或表结构版本不对,会抛出异常)。

  • org.flowable.dmn.engine.impl.cfg.StandaloneInMemDmnEngineConfiguration: 这是一个便于使用单元测试的类。Flowable DMN自行处理事务。默认使用H2内存数据库。数据库会在引擎启动时创建,并在引擎关闭时删除。使用这个类时,很可能不需要更多的配置。

  • org.flowable.dmn.spring.SpringDmnEngineConfiguration: 在流程引擎处于Spring环境时使用。查看Spring集成章节获得更多信息。

2.3. 插入流程引擎 Plug into Process Engine

除了在独立模式下运行之外,也可能需要将DMN引擎插入流程引擎中。这样可以使流程引擎能够使用DMN和其他引擎。这样就可以,例如,让流程引擎的部署服务API可以部署的包中,不止包含BPMN模型,还可以包含DMN模型。

要在流程引擎中使用DMN引擎,需要在流程引擎配置文件的configurators列表中,添加org.flowable.dmn.engine.configurator.DmnEngineConfigurator。

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

有两种方式配置Flowable DMN引擎使用的数据库。第一种方式是定义数据库的JDBC参数:

  • jdbcUrl: 数据库的JDBC URL。

  • jdbcDriver: 特定数据库类型的驱动实现。

  • jdbcUsername: 用于连接数据库的用户名。

  • jdbcPassword: 用于连接数据库的密码。

通过提供的JDBC参数构造的数据源,使用默认的MyBatis连接池设置。可用下列属性调整这个连接池(来自MyBatis文档):

  • jdbcMaxActiveConnections: 连接池能够容纳的最大活动连接数量。默认值为10.

  • jdbcMaxIdleConnections: 连接池能够容纳的最大空闲连接数量。

  • jdbcMaxCheckoutTime: 连接从连接池“取出”后,被强制返回前的最大时间间隔,单位为毫秒。默认值为20000(20秒)。

  • jdbcMaxWaitTime: 这是一个底层设置,在连接池获取连接的时间异常长时,打印日志并尝试重新获取连接(避免连接池配置错误造成的永久沉默失败。默认值为20000(20秒)。

数据库配置示例:

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

我们的跑分显示MyBatis连接池在处理大量并发请求时,并不是最经济或最具弹性的。因此,建议使用javax.sql.DataSource的实现,并将其注入到流程引擎配置中(例如DBCP、CP30、Hikari、Tomcat连接池,等等):

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

请注意Flowable DMN发布时不包括用于定义数据源的库。需要自行把库放在你的classpath中。

无论使用JDBC还是数据源方式配置,下列参数都可以使用:

  • databaseType: 通常不需要专门设置这个参数,因为它可以从数据库连接信息中自动检测得出。只有在自动检测失败时才需要设置。可用值:{h2, mysql, oracle, postgres, mssql, db2}。这个选项会决定创建、删除与查询时使用的脚本。查看“支持的数据库”章节了解我们支持哪些类型的数据库。

  • databaseSchemaUpdate: 用于设置流程引擎启动关闭时使用的数据库表结构控制策略。

    • false (默认): 当引擎启动时,检查数据库表结构的版本是否匹配库文件版本。版本不匹配时抛出异常。

    • true: 构建引擎时,检查并在需要时更新表结构。表结构不存在则会创建。

    • create-drop: 引擎创建时创建表结构,并在引擎关闭时删除表结构。

2.5. JNDI数据源配置 JNDI Datasource Configuration

默认情况下,Flowable DMN的数据库配置保存在每个web应用WEB-INF/classes目录下的db.properties文件中。有时这样并不合适,因为这需要用户修改Flowable源码中的db.properties文件并重新编译war包,或者在部署后解开war包并修改db.properties文件。

通过使用JNDI(Java Naming and Directory Interface,Java命名和目录接口)获取数据库连接时,连接就完全由Servlet容器管理,并可以在war部署之外管理配置。同时也提供了比db.properties中更多的控制连接的参数。

2.5.1. 配置 Configuration

根据你使用的servlet容器应用不同,配置JNDI数据源的方式也不同。下面的介绍用于Tomcat,对于其他容器应用,请参考对应的文档。

Tomcat的JNDI资源配置在$CATALINA_BASE/conf/[enginename]/[hostname]/[warname].xml (对于Flowable UI应用,通常会是$CATALINA_BASE/conf/Catalina/localhost/flowable-app.xml)。当应用第一次部署时,默认会从Flowable war包中复制context.xml。所以如果存在这个文件则需要替换。例如,如果需要将JNDI资源修改为应用连接MySQL而不是H2,按照下列修改文件:

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参数 JNDI properties

要配置JNDI数据源,在Flowable UI应用的配置文件中使用下列参数:

  • datasource.jndi.name: 数据源的JNDI名

  • datasource.jndi.resourceRef: 设置是否在J2EE容器中查找。也就是说,如果JNDI名中没有包含"java:comp/env/"前缀,是否需要添加它。默认为"true"。

2.6. 支持的数据库 Supported databases

下面列出Flowable用于引用数据库的类型(区分大小写!)。

Flowable DMN数据库类型 示例JDBC URL 备注

h2

jdbc:h2:tcp://localhost/flowable_dmn

默认配置的数据库

mysql

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

已使用mysql-connector-java数据库驱动测试

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) 或 jdbc:jtds:sqlserver://localhost:1433/flowable_dmn (jdbc.driver=net.sourceforge.jtds.jdbc.Driver)

已使用Microsoft JDBC Driver 4.0 (sqljdbc4.jar)与JTDS Driver测试

2.7. 创建数据库表 Creating the database tables

Flowable DMM使用Liquibase追踪、管理与应用数据库表结构变更。

在你的数据库中创建数据库表,最简单的方法是:

  • 在classpath中增加flowable-dmn-engine JAR

  • 增加合适的数据库驱动

  • 在classpath中增加Flowable配置文件(flowable.dmn.cfg.xml),指向你的数据库(参考数据库配置)

  • 执行DbSchemaCreate类的main方法

2.8. 数据库表名说明 Database table names explained

Flowable DMN的所有数据库表都以ACT_DMN_开头。

  • ACT_DMN_DATABASECHANGELOG: 由Liquibase使用,用于追踪表结构修改。

  • ACT_DMN_DATABASECHANGELOGLOCK: 由Liquibase使用,用于确保同时只有一个运行的Liquibase实例。

  • ACT_DMN_DECISION_TABLE: 保存已部署的选择表的元数据。

  • ACT_DMN_DEPLOYMENT: 保存部署的元数据。

  • ACT_DMN_DEPLOYMENT_RESOURCE: 保存DMN定义的资源和元数据。

2.9. 数据库升级 Database upgrade

在升级前,请确保你已经(使用数据库的备份功能)备份了数据库。

默认情况下,每次流程引擎创建时会进行版本检查,通常是在你的应用或者Flowable web应用启动的时候。如果Flowable库发现库版本与Flowable数据库表版本不同,会抛出异常。

要进行升级,首先需要将下列配置参数放入你的flowable.dmn.cfg.xml配置文件:

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>

同时,在classpath中加上合适的数据库驱动。升级你应用中的Flowable DMN库,或者启动一个新版本的Flowable DMN,并将它指向包含旧版本数据的数据库。将databaseSchemaUpdate设置为true。当Flowable DMN发现库与数据库表结构不同步时,会自动将数据库表结构升级至新版本。

2.10. 配置部署缓存 Deployment cache configuration

鉴于选择表信息不会改变,为了避免每次使用选择表时都读取数据库,所有的选择配置都会(在解析后)被缓存。默认情况下,这个缓存没有限制。要限制选择缓存,加上如下的参数

1
<property name="decisionCacheLimit" value="10" />

设置这个参数,会将默认的hashmap替换为LRU缓存,以进行限制。当然,参数的“最佳”取值,取决于总的选择定义数量,以及实际使用的选择定义数量。

你也可以注入自己的缓存实现。它必须是一个实现了org.flowable.dmn.engine.impl.persistence.deploy.DeploymentCache接口的bean:

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

2.11. 日志 Logging

所有的日志(Flowable、Spring、MyBatis等)都通过SLF4J路由,并允许你自行选择日志实现。

默认情况下,Flowable引擎依赖中不提供SFL4J绑定jar。你需要自行将其加入你的项目,以便使用所选的日志框架。如果没有加入实现jar,SLF4J会使用NOP-logger。这时除了一条警告外,不会记录任何日志。可以从http://www.slf4j.org/codes.html#StaticLoggerBinder了解关于绑定的更多信息。

可以像这样(这里使用Log4j)使用Maven添加依赖,请注意你还需要加上版本:

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

Flowable-UI与Flowable-rest web应用配置为使用Log4j绑定。运行所有flowable-*模块的测试时也会使用Log4j。

重要提示:当使用classpath中带有commons-logging的容器时:为了将spring的日志路由至SLF4j,需要使用桥接(参考http://www.slf4j.org/legacy.html#jclOverSLF4J)。如果你的容器提供了commons-logging实现,请按照http://www.slf4j.org/codes.html#release页面的指示来保证稳定性。

使用Maven的示例(省略了版本):

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

3. The Flowable DMN API

3.1. DMN引擎API与服务 The DMN Engine API and services

DMN引擎API是与Flowable DMN交互的最常用手段。其入口是DmnEngine,并像配置章节中介绍的一样,可以使用多种方式创建。使用DmnEngine,可以获得各种其他服务。DmnEngine与服务对象都是线程安全的,因此可以在整个服务器中保存一份引用。

1 2 3 4
DmnEngine dmnEngine = DmnEngines.getDefaultDmnEngine(); DmnRuleService dmnRuleService = dmnEngine.getDmnRuleService(); DmnRepositoryService dmnRepositoryService = dmnEngine.getDmnRepositoryService(); DmnManagementService dmnManagementService = dmnEngine.getDmnManagementService();

DmnEngines.getDefaultDmnEngine()在第一次被调用时将初始化并构建DMN引擎,在之后的调用都会返回相同的DMN引擎。DMN引擎的创建通过DMNEngines.init()实现,关闭由DMNEngines.destroy()实现。

DmnEngines会扫描所有flowable.dmn.cfg.xml与flowable-dmn-context.xml文件。对于所有的flowable.dmn.cfg.xml文件,DMN引擎会以标准Flowable方式构建引擎:DmnEngineConfiguration.createDmnEngineConfigurationFromInputStream(inputStream).buildDmnEngine()。对于所有的flowable-dmn-context.xml文件,DMN引擎会以Spring的方式构建:首先构建Spring应用上下文,然后从该上下文中获取DMN引擎。

所有的服务都是无状态的。这意味着你可以很容易的在集群环境的多个节点上运行Flowable DMN,使用同一个数据库,而不用担心上一次调用实际在哪台机器上执行。不论在哪里执行,对任何服务的任何调用都是幂等(idempotent)的。

DmnRepositoryService很可能是使用Flowable DMN引擎要用的第一个服务。这个服务提供了管理与控制部署(deployments)与DMN定义(DMN definitions)的操作。DMN定义是DMN模型的基础概念(DMN的主要概念在DMN介绍章节中介绍)。它包含了选择(decision)以及对应的选择表(decision table)。部署(deployment)是Flowable DMN引擎中的包装单元,一个部署中可以包含多个DMN XML文件。部署意味着将它上传至引擎,引擎将在储存至数据库之前检查与分析所有的DMN定义。从这里开始,可以在系统中使用这个部署,部署中包含的所有选择都可以使用。

此外,这个服务还可以:

  • 查询引擎已知的部署、DMN定义与选择表。

  • 获取POJO版本的DMN定义或选择表。使用它可以用Java而不是XML的方式检查选择。

DmnRuleService提供执行选择的方法。提供参数和输入参数,就可以开始计算选择。

DmnManagementService通常在用Flowable DMN编写用户应用时不需要使用。它可以获取关于引擎版本、数据库表以及数据库内容的信息。

参考javadocs了解服务操作与DMN引擎API的更多信息。

3.2. 异常策略 Exception strategy

Flowable的异常基类是org.flowable.engine.FlowableException,这是一个未检查异常(unchecked exception)。在任何API操作时都可能会抛出这个异常,javadoc记录了每个方法可能发生的异常。例如,从DmnRuleService中摘录:

1 2 3 4 5 6 7 8 9 10 11 12
/** * 按照key查找并执行一个选择。 --Execute a decision identified by it's key. * * @param decisionKey 选择的key,不能为null。 --the decision key, cannot be null * @param inputVariables 包含输入变量的map。 --map with input variables * @return 执行的{@link RuleEngineExecutionResult}。 --the {@link RuleEngineExecutionResult} for this execution * @throws FlowableObjectNotFoundException * 如果给定key不存在。 --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);

在上例中,如果传递的key找不到选择,会抛出异常。并且,由于javadoc中明确要求decisionKey不能为null,因此如果传递了null值,会抛出FlowableIllegalArgumentException异常。

尽管我们想避免过大的异常层次结构,在特定情况下仍然会抛出下述异常子类。所有流程执行与API调用中发生的错误,如果不符合下面列出的异常,会统一抛出FlowableExceptions。

  • FlowableOptimisticLockingException: 当对同一数据实体的并发访问,导致数据存储发生乐观锁时抛出。

  • FlowableClassLoadingException: 当需要载入的类(如JavaDelegates, TaskListeners, …​)无法找到,或载入时发生错误时抛出。

  • FlowableObjectNotFoundException: 当请求或要操作的对象不存在时抛出。

  • FlowableIllegalArgumentException: 这个异常说明调用Flowable DMN API时使用了不合法的参数。可能是引擎配置中的不合法值,或者是API调用传递的不合法参数。

3.3. 查询API (Query API)

从引擎中查询数据有两种方式:查询API与原生(native)查询。查询API可以使用链式API,通过编程方式进行类型安全的查询。你可以在查询中增加各种条件(所有条件都用做AND逻辑),也可以明确指定排序。下面是示例代码:

1 2 3 4
List<DmnDeployment> dmnDeployments = dmnRepositoryService.createDeploymentQuery() .deploymentNameLike("deployment%") .orderByDeployTime() .list();

有时你需要更强力的查询,例如使用OR操作符查询,或者使用查询API不能满足查询条件要求。我们为这种需求提供了可以自己写SQL查询的原生查询。返回类型由使用的查询对象决定,数据也会映射到正确的对象中(Task、ProcessInstance、Execution,等等)。查询会在数据库中进行,因此你需要使用数据库中定义的表名与列名。这需要了解内部数据结构,因此建议小心使用原生查询。数据库表名可以通过API读取,这样可以将依赖关系减到最小。

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

Flowable是嵌入式的Java引擎,因此为业务流程编写单元测试就与编写一般的单元测试一样简单。

Flowable支持JUnit V4的单元测试风格。撰写JUnit 4测试用例时,可以使用org.flowable.dmn.engine.test.FlowableDmnRule Rule。使用这个Rule,就可以通过getter访问DMN引擎和服务。引入这个Rule就可以使用org.flowable.dmn.engine.test.DmnDeploymentAnnotation注解(参见上例解释其用途及配置),并且会自动在classpath中寻找默认配置文件。当使用相同的配置资源时,流程引擎会静态缓存,以用于多个单元测试。也可以为Rule提供自定义的引擎配置。

下面的代码片段展示了JUnit 4风格的测试与FlowableDmnRule的用法(并传入了一个可选的自定义配置):

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. Web应用中的DMN引擎 The DMN engine in a web application

DmnEngine是线程安全的类,可以很容易地在多个线程间共享。在web应用中,这意味着可以在容器启动时创建DMN引擎,并在容器关闭时关闭引擎。

下面的代码片段展示了如何在纯Servlet环境中,简单的通过ServletContextListener初始化与销毁流程引擎。

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(); } }

contextInitialized方法会调用ProcessEngines.init()。它会在classpath中查找flowable.dmn.cfg.xml资源文件,并为每个配置分别创建DmnEngine(例如多个JAR都包含配置文件)。如果在classpath中有多个这样的资源文件,请确保它们都使用不同的名字。需要使用DMN引擎时,可以获取通过:

1
DmnEngines.getDefaultDmnEngine()

或者:

1
DmnEngines.getDmnEngine("myName");

当然,就像配置章节中介绍的,还可以使用各种不同的方式创建DMN引擎。

context-listener的contextDestroyed方法会调用ProcessEngines.destroy()。它会妥善关闭所有已初始化的流程引擎。

4. 集成Spring (Spring integration)

尽管完全可以脱离Spring使用Flowable DMN,我们仍提供了很多非常好的集成特性,并将在这一章节介绍。

4.1. DmnEngineFactoryBean

DmnEngine可以被配置为普通的Spring bean。集成起点是org.flowable.dmn.spring.DmnEngineFactoryBean类。这个bean处理DMN引擎配置,并创建DMN引擎。这意味着在Spring中,创建与设置参数与配置章节 configuration section中介绍的一样。集成Spring的配置与引擎bean为:

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>

请注意dmnEngineConfiguration bean现在使用org.flowable.dmn.spring.SpringDmnEngineConfiguration类。

4.2. 自动部署资源 Automatic resource deployment

集成Spring还提供了部署资源的特殊方式。在DMN引擎配置中,可以指定一组资源。当DMN引擎被创建时,这些资源都会被扫描并部署。有过滤器用于阻止重复部署。只有当资源确实发生变化时,才会重新部署至Flowable DMN数据库。在Spring容器经常重启(例如测试时)的时候,这很有用。

这里有个例子:

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>

默认情况下,这个配置会将符合这个过滤器的所有资源组织在一起,作为Flowable DMN引擎的一个部署。重复检测过滤器将作用于整个部署,避免重复地部署未改变资源。有时这不是你想要的。例如,如果用这种方式部署了一组DMN资源,即使只有其中的一个资源发生了改变,整个部署都会被认为已经改变,因此这个部署中所有的所有DMN定义都会被重新部署。这将导致每个DMN定义都会刷新版本号,即使实际上只有一个DMN发生了变化。

可以使用SpringDmnEngineConfiguration中的额外参数deploymentMode,定制部署的选择方式。这个参数定义了在一组符合过滤器的资源中,组织部署的方式。默认这个参数有3个可用值:

  • default: 将所有资源组织在一个部署中,整体用于重复检测过滤。这是默认值,在未设置这个参数时也会用这个值。

  • single-resource: 为每个资源创建一个单独的部署,并用于重复检测过滤。当你希望单独部署每一个DMN定义,并且在它发生变化时创建新的DMN定义版本,应该使用这个值。

  • resource-parent-folder: 为同一个目录下的资源创建一个单独的部署,并用于重复检测过滤。这个参数值可以为大多数资源创建独立的部署。同时仍可以通过将部分资源放在同一个目录下,将它们组织在一起。这里有一个将deploymentMode设置为single-resource的例子:

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>

如果上述deploymentMode的参数值不能满足要求,还可以自定义组织部署的行为。可以创建SpringDmnEngineConfiguration的子类,并覆盖getAutoDeploymentStrategy(String deploymentMode)方法。这个方法决定了对于给定的deploymentMode参数值,使用何种部署策略。

4.3. 单元测试 Unit testing

与Spring集成后,选择就可以非常简单地使用标准的 Flowable测试工具 Flowable testing facilities进行测试。下面的例子展示了如何通过典型的基于Spring的单元测试,对选择进行测试:

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")); } }

请注意要让这个例子可以正常工作,需要在Spring配置中定义org.flowable.dmn.engine.test.FlowableDmnRule bean(在上面的例子中通过auto-wiring注入)。

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

5. 部署 Deployment

5.1. DMN定义 DMN Definitions

可以在DMN引擎中部署带有.dmn扩展名的DMN定义。

如果DMN引擎已经插入流程引擎,就可以与其他流程相关资源一起,将DMN定义打包进业务存档(BAR)文件中。流程引擎部署服务会将DMN资源部署至DMN引擎。

业务存档中的Java类不会添加至classpath。业务存档中,所有选择使用的自定义类,都需要在用于运行选择的Flowable (DMN)引擎的classpath下。

5.1.1. DMN定义,选择及选择表 DMN Definitions, decisions and decision tables

DMN定义由选择(decision)和其他东西组成。选择有一个表达式。DMN标准描述了几种表达式的类型。目前在Flowable DMN中,我们支持选择表(decision table)类型的表达式。在部署DMN定义时,所有选择,每个可以包含一个选择表,将分别插入至ACT_DMN_DECISION表中。

5.1.2. 编程方式部署 Deploying programmatically

可以这样部署一个DMN定义:

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类 Java classes

所有自定义表达式函数中用到的自定义类,在执行选择时,都需要存在于引擎的classpath中。

然而在部署DMN定义时,classpath中不是必须要有这些类。

当使用演示配置,且希望添加自定义类时,需要在flowable-ui-app或flowable-app-rest webapp的 lib中,添加包含有你的自定义类的JAR。别忘了也要添加你的自定义类的依赖(若有)。或者,也可以将你的依赖添加到Tomcat的库文件夹,${tomcat.home}/lib中。

5.1.4. 创建单独应用 Creating a single app

如果不想费心保证所有DMN引擎都在classpath中含有所有需要的代理类,以及保证它们都使用了正确的Spring配置,也可以考虑将flowable-rest web应用嵌入你自己的web应用,这样就只有一个单独的DmnEngine。

5.2. DMN选择的版本 Versioning of DMN decisions

DMN并没有版本的概念。这其实很好,因为可执行的DMN定义文件很可能已经作为你的开发项目的一部分,保存在版本管理系统仓库中了(例如Subversion,Git,或者Mercurial)。在部署时,会创建DMN定义的版本。在部署时,Flowable会在保存至Flowable数据库前,为decision指定版本。

对于DMN定义中的每个DMN选择,下列步骤都会执行,以初始化key、version、name与id参数:

  • XML文件中选择的id属性作为选择表的key参数。

  • XML文件中选择的name属性作为选择表的name参数。

  • 当每个key的选择第一次部署时,指定版本为1。对其后所有使用相同key的选择,部署时版本会在该key当前已部署的最高版本号基础上加1。key参数用于区分选择。

  • id参数是一个唯一数字,用以保证在集群环境下,选择表缓存中,选择表标识的唯一性。

以下面的选择为例:

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

当部署这个选择时,数据库中的选择表会是这个样子:

id key name version

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

myDecision

My important decision

1

如果我们现在部署同一个选择的更新版本,且保持选择的id不变,那么选择表中会包含下面的记录:

id key name version

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

myDecision

My important decision

1

e9c2a6c0-c085-11e6-9096-6ab56fad108a

myDecision

My important decision

2

当调用dmnRuleService.executeDecisionByKey("myDecision")时,会使用版本2的选择定义,因为这是这个选择定义的最新版本。

如果再创建第二个选择,如下定义并部署至Flowable DMN,表中会增加第三行。

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

表将显示类似:

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

请注意新选择的key与第一个选择的不同。即使name是相同的(我们可能本应该也改变它),Flowable DMN只用id属性来区分选择。因此新的选择部署时版本为1.

5.3. 类别 Category

DMN部署与选择表都可以定义类别。部署的类别可以这样使用API指定:

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

选择表的类别可以这样使用API定义:

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

6. DMN 1.1介绍 DMN 1.1 Introduction

6.1. DMN是什么? What is DMN?

选择模型与注解(Decision Model and Notation, DMN)是由Object Management Group发布的标准。是用于描述与建模组织中可重复的选择的标准方式,用以确保选择模型可以在组织间公用。

6.2. DMN定义是什么 What is a DMN definition

DMN 1.1概要(schema)的根元素是definitions元素。在这个元素内,可以定义多个选择定义(尽管我们建议在每个文件中,只有一个选择定义。这样可以简化之后再部署过程的管理)。在每个选择中,可以定义一个表达式。表达式有多种类型。在Flowable中,目前只支持选择表(decision table)类型的表达式。

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. 创建一个DMN定义 Creating a DMN definition

可以使用文本编辑器创建DMN定义。但是在这个例子中,我们使用Flowable modeler中提供的选择表编辑器创建。

我们将实现一个非常简单的用例:根据用户分类,决定折扣比例。

在Flowable modeler中打开选择表界面。

decision tables 1

并选择Create Decision Table(创建选择表)。

decision tables 2

提供一个选择表名,以及唯一的选择表key,并选中Create new decision table(创建新选择表)。

decision tables 3

这样就可以开始定义你的选择表了。让我们介绍一下编辑器的界面。

6.3.1. 命中策略 Hit Policy

在左上角可以选择一个命中策略。

可以使用两种命中策略:first(首先,单选)和any(任意,单选)。若使用首先命中策略,则选择表的执行会在某条规则有效时停止。若使用任意命中策略,将执行所有有效的规则。

6.3.2. 输入与输出表达式 Input and Output expressions

选择表分成两个区域:蓝色和绿色。在蓝色区域中是输入表达式;在绿色区域中是输出表达式。

decision tables 4

在输入表达式中,可以定义变量,用于规则输入项(input entries)的表达式(在下面解释)。可以通过选择Add Input(添加输入),定义多个输入表达式。

decision tables 5

在输出表达式中,可以定义选择表执行结果要创建的变量(变量的值将用于输出项表达式,在下面解释)。可以通过选择Add Output(添加输出),定义多个输出表达式。

6.3.3. 规则 Rules

每个规则包含一个或多个输入项,以及一个或多个输出项。输入项是一个表达式,将使用(该列的)输入变量计算。如果所有的输入项都计算为true,则规则结果为true,并将计算输出项。

DMN标准定义了一个表达式语言:(S)-FEEL。目前,我们还不支持这部分标准。在Flowable DMN中,我们使用MVEL作为表达式语言。

decision tables 6

双击对应的单元格,录入输入表达式。在这个例子中,录入了表达式== "BRONZE"。与相应的输入表达式(列头)的变量定义结合,就在运行时产生了完整的表达式customerCat == "BRONZE"。

decision tables 7

双击对应的单元格,录入输出表达式。在这个例子中,录入了表达式5。 这实际上更像一个隐含赋值。当规则的所有输入项都计算为true时,相应的输出项(列)的变量将赋值为5.

我们可以继续添加更多规则(点击Add Rule,添加规则),以完成选择表。

decision tables 8

在我们的例子中,规则4使用空输入项。空输入项将被引擎计算为true。这意味着如果其他规则都失效的话,规则4的输出将成为选择表的输出。在这个场景中,变量discountPerc的值将设置为0。

decision tables 9

这样就可以保存选择表了。需要提供一个唯一的选择表key。

6.4. 在BPMN2.0流程中使用 Use in a BPMN2.0 process

可以在一个BPMN2.0流程中,引入一个选择任务(Decision task),并选中引用选择表(Decision table reference),来使用新创建的选择表。

decision tables 10

在上面的流程中,有一个启动表单,为流程实例(及选择表)提供客户分类(customer category)。Display Discount(显示折扣)用户任务,将使用一个表达式表单字段及表达式${discountperc},显示选择表的结果。

6.5. DMN 1.1 XML

上面例子的完整DMN 1.1 XMl如下:

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>

在这里请注意,Flowable中使用的选择表key,是DMN XML中的选择id。

7. DMN REST API

7.1. Flowable DMN REST一般原则 General Flowable DMN REST principles

7.1.1. 安装与认证 Installation and Authentication

Flowable DMN在DMN引擎中包含了REST API,可以通过在servlet容器如Apache Tomcat中,部署flowable-app-rest.war文件来安装。但是也可以在其他的web应用中使用,只要在你的应用中包含这些servlet及其mapping,并在classpath中添加所有flowable-dmn-rest模块的依赖即可。

默认情况下Flowable DMN引擎连接至一个H2内存数据库。可以修改WEB-INF/classes文件夹下的db.properties文件中的数据库设置。DMN REST API使用JSON格式 (http://www.json.org) ,基于Spring MVC (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html) 构建。

默认情况下,所有REST资源都需要有一个有效的Flowable已认证用户。我们使用基础HTTP访问认证。因此在请求时,可以在HTTP头添加 Authorization: BasicXXX== ,也可以在请求url中包含用户名与密码(例如http://username:password@localhost:8080/xyz)。

建议使用基础认证时,同时使用HTTPS。

7.1.2. 配置 Configuration

Flowable REST web应用(flowable-app-rest)使用Spring Java Configuration来启动Flowable引擎、定义基础认证安全使用Spring security,以及为特定的变量处理定义变量转换。可以修改WEB-INF/classes目录下的engine.properties文件,定义少量参数。如果需要高级配置选项,可以在flowable-custom-context.xml文件中覆盖默认的Spring bean,这个文件也在WEB-INF/classes目录下。该文件中已经以注释形式提供了示例配置。也可以在这里重载默认的RestResponseFactories。对于DMN引擎来说,就是定义一个新的命名为dmnResponsefactory的Spring bean,使用自定义实现类。

7.1.3. 在Tomcat中使用 Usage in Tomcat

由于Tomcat中的默认安全参数,默认不能使用已转义斜线符(%2F与%5C)(返回400结果)。这可能会影响部署资源与其数据URL,因为URL可能隐含已转义斜线符。

当发现非预期的400结果时,设置下列系统参数:

-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

最佳实践是(post/put JSON时),在下面描述的HTTP请求中,永远将Accept与Content-Type头设置为application/json。

7.1.4. 方法与返回码 Methods and return-codes

Table 1. HTTP方法与相应操作
方法 操作

GET

获取单个资源,或获取一组资源。

POST

创建一个新资源。在查询结构太复杂,不能放入GET请求的查询URL中时,也用于执行资源查询。

PUT

更新一个已有资源的参数。也用于在已有资源上的调用动作。

DELETE

删除一个已有资源。

Table 2. HTTP方法响应码
响应 描述

200 - Ok

操作成功,返回响应(GET与PUT请求)。

201 - 已创建

操作成功,已经创建了实体,并在响应体中返回(POST请求)。

204 - 无内容

操作成功,已经删除了实体,因此没有返回的响应体(DELETE请求)。

401 - 未认证

操作失败。操作要求设置认证头。如果请求中有认证头,则提供的鉴证并不合法,或者用户未被授权进行该操作。

403 - 禁止

操作被禁止,且不应重试。这不是鉴证或授权的问题,而是说明不允许该操作。例如:删除一个运行中流程的任务是且永远是不允许的,无论该用户或流程/任务的状态。

404 - 未找到

操作失败。请求的资源未找到。

405 - 不允许的方法

操作失败。使用的方法不能用于该资源。例如,更新(PUT)部署资源将导致405状态。

409 - 冲突

操作失败。该操作导致更新一个已被其他操作更新的资源,因此本更新不再有效。也可以表明正在为一个集合创建一个资源,但该集合中已经使用了该标识符。

415 - 不支持的媒体类型

操作失败。请求提包含了不支持的媒体类型。也会发生在请求体JSON中包含了未知的属性或值,但没有正确的格式/类型来接受的情况下。

500 - 服务器内部错误

操作失败。执行操作时发生了未知异常。响应体中包含了错误的细节。

HTTP响应的media-type总是application/json,除非请求的是二进制内容(例如部署资源数据)。这时将使用内容的media-type。

7.1.5. 错误响应体 Error response body

当发生错误时(客户端与服务器端都可能,4XX及5XX状态码),响应体会包含一个描述了发生的错误的对象。选择未找到时的404状态的例子:

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

7.1.6. 请求参数 Request parameters

URL片段 URL fragments

作为url的一部分的参数(例如,http://host/flowable-rest/dmn-api/dmn-repository/deployments/{deploymentId}中的deploymentId参数),如果包含特殊字符,则需要进行合适的转义(参见URL编码或百分号编码)。大多数框架都内建了这个功能,但要记得考虑它。特别是对可能包含斜线符的段落(例如部署资源),就是必须的。

Rest URL查询参数 Rest URL query parameters

作为查询字符串添加在URL中的参数(例如http://host/flowable-rest/dmn-api/dmn-repository/deployments/?name=Deployment中的name参数)可以使用下列类型,也会在相应的REST-API文档中提到:

Table 3. URL查询参数类型
类型 格式

String

纯文本参数。可以包含任何URL允许的合法字符。对于XXXLike参数,字符串可能会包含通配符%(需要进行URL编码)。可以进行like搜索,例如,'Tas%'将匹配所有以’Tas’开头的值。

Integer

整形参数。只能包含数字型非十进制值(原文如此,下同),在-2.147.483.648至2.147.483.647之间。

Long

长整形参数。只能包含数字型非十进制值,在-9.223.372.036.854.775.808至9.223.372.036.854.775.807之间。

Boolean

boolean型参数。可以为true或false。任何其他值都会导致'405 - 错误请求'响应。

Date

日期型参数。使用ISO-8601日期格式(参考wikipedia中的ISO-8601),使用时间与日期部分(例如2013-04-03T23:45Z)。

JSON体参数 JSON body parameters
Table 4. JSON参数类型
类型 格式

String

纯文本参数。对于XXXLike参数,字符串可能会包含通配符%。可以进行like搜索。例如,'Tas%'将匹配所有以’Tas’开头的值。

Integer

整形参数,使用JSON数字。只能包含数字型非十进制值(原文如此,下同),在-2.147.483.648至2.147.483.647之间。

Long

长整形参数,使用JSON数字。只能包含数字型非十进制值,在-9.223.372.036.854.775.808至9.223.372.036.854.775.807之间。

Date

日期型参数,使用JSON文本。使用ISO-8601日期格式(参考wikipedia中的ISO-8601),使用时间与日期部分(例如2013-04-03T23:45Z)。

分页与排序 Paging and sorting

分页与排序参数可以作为查询字符串加入URL中(例如http://host/flowable-rest/dmn-api/dmn-repository/deployments?sort=name中的name参数)。

Table 5. 查询变量参数
参数 默认值 描述

sort

各查询实现不同

排序键的名字,在各查询实现中默认值与可用值都不同。

order

asc

排序顺序,可以是’asc'(顺序)或’desc'(逆序)。

start

0

对结果分页的参数。默认结果从0开始。

size

10

对结果分页的参数。默认大小为10.

JSON查询变量格式 JSON query variable format
1 2 3 4 5 6
{ "name" : "variableName", "value" : "variableValue", "operation" : "equals", "type" : "string" }
Table 6. JSON查询变量参数
参数 必填 描述

name

否

包含在查询中的变量名。在有些使用'equals'的查询中可以为空,查询任意变量名为给定值的资源。

value

是

包含在查询中的变量值,需要使用给定类型的正确格式。

operator

是

查询使用的操作,可以为下列值:equals, notEquals, equalsIgnoreCase, notEqualsIgnoreCase, lessThan, greaterThan, lessThanOrEquals, greaterThanOrEquals与like。

type

否

所用变量的类型。当省略时,会从value参数推理类型。任何JSON文本值都认为是string类型,JSON boolean值认为是boolean类型,JSON数字认为是long或integer,取决于数字的大小。建议在有疑惑时明确指定类型。其他支持的类型列在下面。

Table 7. 默认查询JSON类型
类型名 描述

string

值处理转换为java.lang.String。

short

值处理转换为java.lang.Integer。

integer

值处理转换为java.lang.Integer。

long

值处理转换为java.lang.Long。

double

值处理转换为java.lang.Double。

boolean

值处理转换为java.lang.Boolean。

date

值处理转换为java.util.Date。JSON字符串将使用ISO-8601日期格式转换。

变量表示 Variable representation

当使用变量时(执行选择),读取与写入时REST-api都使用一些通用原则与JSON格式。变量的JSON表示像是这样:

1 2 3 4 5 6
{ "name" : "variableName", "value" : "variableValue", "valueUrl" : "http://...", "type" : "string" }
Table 8. 变量的JSON属性
参数 必填 描述

name

是

变量名。

value

否

变量的值。当写入变量且省略了value时,会使用null作为value。

valueUrl

否

当读取binary或serializable类型的变量时,这个属性将指向可用于获取原始二进制数据的URL。

scope

否

变量的范围。如果值为'local,则变量明确定义在其请求的资源上。如果值为global',则变量定义在其父上(或者父树中的任意父)。当写入变量且省略了scope时,使用global。

type

否

变量的类型。查看下面的表格了解类型的更多信息。当写入变量且省略了这个值时,将使用请求的原始JSON属性类型推断,限制在string, double, integer与boolean中。建议总是包含类型,以确保不会错误推断类型。

Table 9. 变量类型
类型名 描述

string

值按照java.lang.String处理。写入变量时使用原始JSON文本。

integer

值按照java.lang.Integer处理。按约定写入变量时使用JSON数字,失败则退回JSON文本。

short

值按照java.lang.Short处理。按约定写入变量时使用JSON数字,失败则退回JSON文本。

long

值按照java.lang.Long处理。按约定写入变量时使用JSON数字,失败则退回JSON文本。

double

值按照java.lang.Double处理。按约定写入变量时使用JSON数字,失败则退回JSON文本。

boolean

值按照java.lang.Boolean处理。按约定写入变量时使用JSON boolean。

date

值按照java.util.Date处理。写入变量时将转换为ISO-8601日期格式。

可以使用自定义JSON表示,以支持额外的变量类型(既可以是简单值,也可以是复杂/嵌套的JSON对象)。通过扩展org.flowable.rest.dmn.service.api.DmnRestResponseFactory的initializeVariableConverters()方法,可以添加额外的org.flowable.rest.variable.RestVariableConverter类,来将你的POJO转换为适合通过REST传输的格式,以及将REST值转换为POJO。实际转换JSON使用Jackson。

7.2. 部署 Deployment

使用tomcat时,请阅读在Tomcat中使用。

7.2.1. DMN部署的列表 List of DMN Deployments

GET dmn-repository/deployments
Table 10. URL查询参数
参数 必填 值 描述

name

否

String

只返回给定名字的部署。

nameLike

否

String

只返回名字like给定名字的部署。

category

否

String

只返回给定分类的部署。

categoryNotEquals

否

String

只返回不是给定分类的部署。

tenantId

否

String

只返回给定tenantId的部署。

tenantIdLike

否

String

只返回tenantId like给定值的部署。

withoutTenantId

否

Boolean

如果值为true,则只返回没有设置tenantId的部署。如果值为false,则忽略withoutTenantId参数。

sort

否

id(默认), name, deploytime’或’tenantId

用于排序的参数,与’order’一起使用。

可以在这个URL中使用通用分页与排序查询参数。

Table 11. REST返回码
返回码 描述

200

代表请求成功。

成功响应体:

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. 获取一个DMN部署 Get a DMN deployment

GET dmn-repository/deployments/{deploymentId}
Table 12. 获取一个部署 - URL参数
参数 必填 值 描述

deploymentId

是

String

要获取的部署的id。

Table 13. 获取一个部署 - 响应码
响应码 描述

200

代表已找到并返回部署。

404

代表未找到请求的部署。

成功响应体:

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. 创建一个新DMN部署 Create a new DMN deployment

POST dmn-repository/deployments

请求体:

请求体需要包含multipart/form-data类型的数据。请求中需要只有一个文件,多余的文件将被忽略。部署名是传入的文件字段的名字。

可以在请求体中传递名为tenantId的额外参数(表单字段)。这个字段的值将指定部署所在的租户(tenant)的id。

Table 14. 创建一个新DMN部署 - 响应码
响应码 描述

201

代表成功创建部署

400

代表请求体中没有内容,或部署不支持content的mime-type。状态描述中包含了额外信息。

成功响应体:

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. 删除一个DMN部署 Delete a DMN deployment

DELETE dmn-repository/deployments/{deploymentId}
Table 15. 删除一个DMN部署 - URL参数
参数 必填 值 描述

deploymentId

是

String

要删除的部署的id。

Table 16. 删除一个DMN部署 - 响应码
响应码 描述

204

代表已找到并删除了部署。响应体设置为空。

404

代表未找到请求的部署。

7.2.5. 获取一个DMN部署的资源内容 Get a DMN deployment resource content

GET dmn-repository/deployments/{deploymentId}/resourcedata/{resourceId}
Table 17. 获取一个DMN部署的资源内容 - URL参数
参数 必填 值 描述

deploymentId

是

String

要获取资源的部署的id。

resourceId

是

String

要获取的资源的id。请确保如果包含斜线符,需要对resourceId进行URL编码。例如,使用’ddecisions%2Fmy-decision.dmn’代替’decisions/my-decision.dmn'。

Table 18. 获取一个DMN部署的资源内容 - 响应码
响应码 描述

200

代表已找到部署与资源,并已返回资源。

404

代表未找到请求的部署,或者该部署中没有给定id的资源。状态描述包含了额外信息。

成功响应体:

响应体将包含所请求资源的二进制资源内容。响应的content-type与资源’mimeType’参数返回的类型相同。同时将设置content-disposition头,让浏览器可以下载文件而不是直接显示。

7.3. 选择表 Decision Tables

7.3.1. 选择表的列表 List of decision tables

GET dmn-repository/decision-tables
Table 19. 选择表的列表 - URL参数
参数 必填 值 描述

version

否

integer

只返回给定版本的选择表。

name

否

String

只返回给定名字的选择表。

nameLike

否

String

只返回名字like给定名字的选择表。

key

否

String

只返回给定key的选择表。

keyLike

否

String

只返回key like给定key的选择表。

resourceName

否

String

只返回给定资源名的选择表。

resourceNameLike

否

String

只返回资源名like给定资源名的选择表。

category

否

String

只返回给定分类的选择表

categoryLike

否

String

只返回分类名like给定名字的选择表。

categoryNotEquals

否

String

只返回不是给定分类的选择表。

deploymentId

否

String

只返回给定id的部署中的选择表。

latest

否

Boolean

只返回选择表的最新版本。只能与’key’及’keyLike’参数一起使用,同时使用任何其它参数都将导致400响应。

sort

否

name(默认), id, key, category, deploymentId’与’version

用于排序的参数,与’order’一起使用。

可以在这个URL中使用通用分页与排序查询参数。

Table 20. 选择表的列表 - 响应码
响应码 描述

200

代表请求成功,并已返回选择表。

400

代表某个参数格式错误,或者’latest’与’key', 'keyLike’以外的其他参数一起使用。状态描述中包含了额外信息。

成功响应体:

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. 获取一个选择表 - URL参数
参数 必填 值 描述

decisionTableId

是

String

要获取的选择表的id。

Table 22. 获取一个选择表 - 响应码
响应码 描述

200

代表已找到并已返回选择表。

404

代表未找到请求的选择表。

成功响应体:

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. 获取一个选择表资源的内容 - URL参数
参数 必填 值 描述

decisionTableId

是

String

要获取资源数据的选择表的id。

响应:

与GET dmn-repository/deployment/{deploymentId}/resourcedata/{resourceId}完全一样的响应码/响应体。

7.3.4. 获取一个选择表的DMN模型 Get a decision table DMN model

GET dmn-repository/decision-tables/{decisionTableId}/model
Table 24. 获取一个选择表的DMN模型 - URL参数
参数 必填 值 描述

decisionTableId

是

String

要获取模型的选择表的id。

Table 25. 获取一个选择表的DMN模型 - 响应码
响应码 描述

200

代表已找到选择表,并已返回模型。

404

代表未找到请求的选择表。

响应体:响应体是一个代表了org.flowable.dmn.model.DmnDefinition的JSON,包含完整的DMN定义模型。

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

请求体:

请求体需要包含multipart/form-data类型的数据。需要提供decisionKey。可选提供tenantId和inputVariables(rest变量)的map。

响应体:

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. 获取DMN引擎信息 Get DMN engine info

GET dmn-management/engine

返回在REST服务中使用的,DMN引擎的只读视图。

成功响应体:

1 2 3 4 5 6
{ "name":"default", "version":"6.0.1", "resourceUrl":"file://flowable-dmn/flowable.dmn.cfg.xml", "exception":null }
Table 26. 获取DMN引擎信息 - 响应码
响应码 描述

200

代表已返回引擎信息。