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中打开选择表界面。
并选择Create Decision Table(创建选择表)。
提供一个选择表名,以及唯一的选择表key,并选中Create new decision table(创建新选择表)。
这样就可以开始定义你的选择表了。让我们介绍一下编辑器的界面。
6.3.1. 命中策略 Hit Policy
在左上角可以选择一个命中策略。
可以使用两种命中策略:first(首先,单选)和any(任意,单选)。若使用首先命中策略,则选择表的执行会在某条规则有效时停止。若使用任意命中策略,将执行所有有效的规则。
6.3.2. 输入与输出表达式 Input and Output expressions
选择表分成两个区域:蓝色和绿色。在蓝色区域中是输入表达式;在绿色区域中是输出表达式。
在输入表达式中,可以定义变量,用于规则输入项(input entries)的表达式(在下面解释)。可以通过选择Add Input(添加输入),定义多个输入表达式。
在输出表达式中,可以定义选择表执行结果要创建的变量(变量的值将用于输出项表达式,在下面解释)。可以通过选择Add Output(添加输出),定义多个输出表达式。
6.3.3. 规则 Rules
每个规则包含一个或多个输入项,以及一个或多个输出项。输入项是一个表达式,将使用(该列的)输入变量计算。如果所有的输入项都计算为true,则规则结果为true,并将计算输出项。
DMN标准定义了一个表达式语言:(S)-FEEL。目前,我们还不支持这部分标准。在Flowable DMN中,我们使用MVEL作为表达式语言。 |
双击对应的单元格,录入输入表达式。在这个例子中,录入了表达式== "BRONZE"。与相应的输入表达式(列头)的变量定义结合,就在运行时产生了完整的表达式customerCat == "BRONZE"。
双击对应的单元格,录入输出表达式。在这个例子中,录入了表达式5。 这实际上更像一个隐含赋值。当规则的所有输入项都计算为true时,相应的输出项(列)的变量将赋值为5.
我们可以继续添加更多规则(点击Add Rule,添加规则),以完成选择表。
在我们的例子中,规则4使用空输入项。空输入项将被引擎计算为true。这意味着如果其他规则都失效的话,规则4的输出将成为选择表的输出。在这个场景中,变量discountPerc的值将设置为0。
这样就可以保存选择表了。需要提供一个唯一的选择表key。
6.4. 在BPMN2.0流程中使用 Use in a BPMN2.0 process
可以在一个BPMN2.0流程中,引入一个选择任务(Decision task),并选中引用选择表(Decision table reference),来使用新创建的选择表。
在上面的流程中,有一个启动表单,为流程实例(及选择表)提供客户分类(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
方法 | 操作 |
---|---|
|
获取单个资源,或获取一组资源。 |
|
创建一个新资源。在查询结构太复杂,不能放入GET请求的查询URL中时,也用于执行资源查询。 |
|
更新一个已有资源的参数。也用于在已有资源上的调用动作。 |
|
删除一个已有资源。 |
响应 | 描述 |
---|---|
|
操作成功,返回响应( |
|
操作成功,已经创建了实体,并在响应体中返回( |
|
操作成功,已经删除了实体,因此没有返回的响应体( |
|
操作失败。操作要求设置认证头。如果请求中有认证头,则提供的鉴证并不合法,或者用户未被授权进行该操作。 |
|
操作被禁止,且不应重试。这不是鉴证或授权的问题,而是说明不允许该操作。例如:删除一个运行中流程的任务是且永远是不允许的,无论该用户或流程/任务的状态。 |
|
操作失败。请求的资源未找到。 |
|
操作失败。使用的方法不能用于该资源。例如,更新(PUT)部署资源将导致 |
|
操作失败。该操作导致更新一个已被其他操作更新的资源,因此本更新不再有效。也可以表明正在为一个集合创建一个资源,但该集合中已经使用了该标识符。 |
|
操作失败。请求提包含了不支持的媒体类型。也会发生在请求体JSON中包含了未知的属性或值,但没有正确的格式/类型来接受的情况下。 |
|
操作失败。执行操作时发生了未知异常。响应体中包含了错误的细节。 |
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文档中提到:
类型 | 格式 |
---|---|
String |
纯文本参数。可以包含任何URL允许的合法字符。对于 |
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型参数。可以为 |
Date |
日期型参数。使用ISO-8601日期格式(参考wikipedia中的ISO-8601),使用时间与日期部分(例如 |
JSON体参数 JSON body parameters
类型 | 格式 |
---|---|
String |
纯文本参数。对于 |
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),使用时间与日期部分(例如 |
分页与排序 Paging and sorting
分页与排序参数可以作为查询字符串加入URL中(例如http://host/flowable-rest/dmn-api/dmn-repository/deployments?sort=name
中的name参数)。
参数 | 默认值 | 描述 |
---|---|---|
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"
}
参数 | 必填 | 描述 |
---|---|---|
name |
否 |
包含在查询中的变量名。在有些使用' |
value |
是 |
包含在查询中的变量值,需要使用给定类型的正确格式。 |
operator |
是 |
查询使用的操作,可以为下列值: |
type |
否 |
所用变量的类型。当省略时,会从 |
类型名 | 描述 |
---|---|
string |
值处理转换为 |
short |
值处理转换为 |
integer |
值处理转换为 |
long |
值处理转换为 |
double |
值处理转换为 |
boolean |
值处理转换为 |
date |
值处理转换为 |
变量表示 Variable representation
当使用变量时(执行选择),读取与写入时REST-api都使用一些通用原则与JSON格式。变量的JSON表示像是这样:
1
2
3
4
5
6 {
"name" : "variableName",
"value" : "variableValue",
"valueUrl" : "http://...",
"type" : "string"
}
参数 | 必填 | 描述 |
---|---|---|
name |
是 |
变量名。 |
value |
否 |
变量的值。当写入变量且省略了 |
valueUrl |
否 |
当读取 |
scope |
否 |
变量的范围。如果值为' |
type |
否 |
变量的类型。查看下面的表格了解类型的更多信息。当写入变量且省略了这个值时,将使用请求的原始JSON属性类型推断,限制在 |
类型名 | 描述 |
---|---|
string |
值按照 |
integer |
值按照 |
short |
值按照 |
long |
值按照 |
double |
值按照 |
boolean |
值按照 |
date |
值按照 |
可以使用自定义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
参数 | 必填 | 值 | 描述 |
---|---|---|---|
name |
否 |
String |
只返回给定名字的部署。 |
nameLike |
否 |
String |
只返回名字like给定名字的部署。 |
category |
否 |
String |
只返回给定分类的部署。 |
categoryNotEquals |
否 |
String |
只返回不是给定分类的部署。 |
tenantId |
否 |
String |
只返回给定tenantId的部署。 |
tenantIdLike |
否 |
String |
只返回tenantId like给定值的部署。 |
withoutTenantId |
否 |
Boolean |
如果值为 |
sort |
否 |
id(默认), name, deploytime’或’tenantId |
用于排序的参数,与’order’一起使用。 |
可以在这个URL中使用通用分页与排序查询参数。
返回码 | 描述 |
---|---|
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}
参数 | 必填 | 值 | 描述 |
---|---|---|---|
deploymentId |
是 |
String |
要获取的部署的id。 |
响应码 | 描述 |
---|---|
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。
响应码 | 描述 |
---|---|
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}
参数 | 必填 | 值 | 描述 |
---|---|---|---|
deploymentId |
是 |
String |
要删除的部署的id。 |
响应码 | 描述 |
---|---|
204 |
代表已找到并删除了部署。响应体设置为空。 |
404 |
代表未找到请求的部署。 |
7.2.5. 获取一个DMN部署的资源内容 Get a DMN deployment resource content
GET dmn-repository/deployments/{deploymentId}/resourcedata/{resourceId}
参数 | 必填 | 值 | 描述 |
---|---|---|---|
deploymentId |
是 |
String |
要获取资源的部署的id。 |
resourceId |
是 |
String |
要获取的资源的id。请确保如果包含斜线符,需要对resourceId进行URL编码。例如,使用’ddecisions%2Fmy-decision.dmn’代替’decisions/my-decision.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
参数 | 必填 | 值 | 描述 |
---|---|---|---|
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中使用通用分页与排序查询参数。
响应码 | 描述 |
---|---|
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}
参数 | 必填 | 值 | 描述 |
---|---|---|---|
decisionTableId |
是 |
String |
要获取的选择表的id。 |
响应码 | 描述 |
---|---|
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
参数 | 必填 | 值 | 描述 |
---|---|---|---|
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
参数 | 必填 | 值 | 描述 |
---|---|---|---|
decisionTableId |
是 |
String |
要获取模型的选择表的id。 |
响应码 | 描述 |
---|---|
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
}
响应码 | 描述 |
---|---|
200 |
代表已返回引擎信息。 |