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.xmlflowable-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选择,下列步骤都会执行,以初始化keyversionnameid参数:

  • 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请求中,永远将AcceptContent-Type头设置为application/json

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

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

GET

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

POST

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

PUT

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

DELETE

删除一个已有资源。

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

200 - Ok

操作成功,返回响应(GETPUT请求)。

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型参数。可以为truefalse。任何其他值都会导致'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, greaterThanOrEqualslike

type

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

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

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

scope

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

type

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

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.DmnRestResponseFactoryinitializeVariableConverters()方法,可以添加额外的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

代表已返回引擎信息。