配置
创建 DMN 引擎
Flowable DMN 引擎的结构与 Flowable 流程引擎非常相似。因此,部分文档与其流程引擎对应内容非常相似。
Flowable DMN 引擎通过名为 flowable.dmn.cfg.xml 的 XML 文件配置。注意,如果你使用以 Spring 方式构建 DMN 引擎,则不适用此方式。
获取 DmnEngine 最简单的方式是使用 org.flowable.dmn.engine.DmnEngines 类:
DmnEngine dmnEngine = DmnEngines.getDefaultDmnEngine()
这会在 classpath 上查找 flowable.dmn.cfg.xml 文件,并基于该文件中的配置构建一个引擎。以下片段展示了一个示例配置。后续章节将详细介绍配置属性。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
<property name="jdbcUrl" value="jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="sa" />
<property name="jdbcPassword" value="" />
<property name="databaseSchemaUpdate" value="true" />
<property name="strictMode" value="false"/>
</bean>
</beans>
注意,配置 XML 实际上是一个 Spring 配置。这并不意味着 Flowable DMN 只能在 Spring 环境中使用! 我们只是在内部利用 Spring 的解析和依赖注入能力来构建引擎。
DMNEngineConfiguration 对象也可以通过配置文件以编程方式创建。也可以使用不同的 bean ID(例如,见第 3 行)。
DmnEngineConfiguration.
createDmnEngineConfigurationFromResourceDefault();
createDmnEngineConfigurationFromResource(String resource);
createDmnEngineConfigurationFromResource(String resource, String beanName);
createDmnEngineConfigurationFromInputStream(InputStream inputStream);
createDmnEngineConfigurationFromInputStream(InputStream inputStream, String beanName);
也可以不使用配置文件,而是基于默认值创建配置
(更多信息参见支持的不同类)。
DmnEngineConfiguration.createStandaloneDmnEngineConfiguration();
DmnEngineConfiguration.createStandaloneInMemDmnEngineConfiguration();
所有这些 DmnEngineConfiguration.createXXX() 方法都返回一个 DmnEngineConfiguration,可在需要时进一步调整。调用 buildDmnEngine() 操作后,即创建了一个 DmnEngine:
DmnEngine dmnEngine = DmnEngineConfiguration.createStandaloneInMemDmnEngineConfiguration()
.setDatabaseSchemaUpdate(DmnEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
.setJdbcUrl("jdbc:h2:mem:my-own-db;DB_CLOSE_DELAY=1000")
.buildDmnEngine();
DmnEngineConfiguration bean
flowable.dmn.cfg.xml 必须包含一个 ID 为 'dmnEngineConfiguration' 的 bean。
<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 环境中使用 DMN 引擎时使用。更多信息参见 Spring 集成章节。
插入流程引擎
除了以独立模式运行外,还可以将 DMN 引擎插入流程引擎。这使流程引擎能够感知它以及其他引擎。例如,这使得可以向流程引擎的部署服务 API 部署不仅包含 BPMN 模型、还包含 DMN 模型的构件。
要让流程引擎感知 DMN 引擎,需要将 org.flowable.dmn.engine.configurator.DmnEngineConfigurator 添加到流程引擎配置中的 configurator 列表。
<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>
数据库配置
配置 Flowable DMN 引擎所使用的数据库有两种方式。第一种方式是定义数据库的 JDBC 属性:
- jdbcUrl:数据库的 JDBC URL。
- jdbcDriver:特定数据库类型驱动程序的实现。
- jdbcUsername:连接数据库的用户名。
- jdbcPassword:连接数据库的密码。
基于所提供 JDBC 属性构造的数据源将具有默认的 MyBatis 连接池设置。可以可选地设置以下属性来调整该连接池(摘自 MyBatis 文档):
- jdbcMaxActiveConnections:连接池在任何时候可包含的最大活动连接数。默认值为 10。
- jdbcMaxIdleConnections:连接池在任何时候可包含的最大 空闲连接数。
- jdbcMaxCheckoutTime:一个连接可以从连接池“检出”多长时间(毫秒)后被强制归还。默认值为 20000(20 秒)。
- jdbcMaxWaitTime:这是一个底层设置,当获取连接耗时异常过长时,给连接池一个打印日志状态并重新尝试获取连接的机会(以避免连接池配置错误时永远静默失败)。默认值为 20000(20 秒)。
数据库配置示例:
<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 实现(例如 HikariCP、Tomcat JDBC Connection Pool 等)并将其注入流程引擎配置:
<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:创建流程引擎时创建模式,关闭流程引擎时删除模式。
-
JNDI 数据源配置
默认情况下,Flowable DMN 的数据库配置包含在每个 web 应用 WEB-INF/classes 下的 db.properties 文件中。这并不总是理想,因为它要求用户要么修改 Flowable 源码中的 db.properties 并重新编译 WAR 文件,要么解包 WAR 并在每次部署时修改 db.properties。
通过使用 JNDI(Java 命名与目录接口)获取数据库连接,连接完全由 Servlet 容器管理,配置可以在 war 部署之外管理。这也允许比 db.properties 文件所提供的方式更灵活地控制连接参数。
配置
JNDI 数据源的配置因你使用的 servlet 容器应用而异。以下说明适用于 Tomcat,但对于其他容器应用,请参阅你的容器应用文档。
如果使用 Tomcat,JNDI 资源在 $CATALINA_BASE/conf/[enginename]/[hostname]/[warname].xml 中配置(对于 Flowable UI,通常为 $CATALINA_BASE/conf/Catalina/localhost/flowable-app.xml)。首次部署应用时,默认上下文会从 Flowable WAR 文件复制,因此如果它已存在,你需要替换它。例如,要将 JNDI 资源更改为让应用连接 MySQL 而非 H2,将文件改为如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/flowable-app">
<Resource auth="Container"
name="jdbc/flowableDB"
type="javax.sql.DataSource"
description="JDBC DataSource"
url="jdbc:mysql://localhost:3306/flowable"
driverClassName="com.mysql.jdbc.Driver"
username="sa"
password=""
defaultAutoCommit="false"
initialSize="5"
maxWait="5000"
maxActive="120"
maxIdle="5"/>
</Context>
JNDI 属性
要配置 JNDI 数据源,请在 Flowable UI 的属性文件中使用以下属性:
- spring.datasource.jndi-name=:数据源的 JNDI 名称。
- datasource.jndi.resourceRef:设置查找是否发生在 J2EE 容器中,换言之,如果 JNDI 名称尚未包含前缀 "java:comp/env/",是否需要添加该前缀。默认值为 "true"。
自定义属性
系统属性也可以在 flowable.dmn.cfg.xml 中使用,格式为 $\{propertyName:defaultValue}。
<property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
<property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
<property name="jdbcUsername" value="${jdbc.username:sa}" />
<property name="jdbcPassword" value="${jdbc.password:}" />
使用此配置时,如果属性 jdbc.url 可用,则将用于 DmnEngineConfiguration 的 jdbcUrl。
否则将使用第一个 : 之后的值。
也可以定义从系统获取属性的位置,方法是使用一个类型为 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 的 bean。
使用自定义属性位置的配置示例
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:/opt/conf/flowable.properties" />
</bean>
<bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
<property name="jdbcUrl" value="${jdbc.url:jdbc:h2:mem:flowable;DB_CLOSE_DELAY=1000}" />
<property name="jdbcDriver" value="${jdbc.driver:org.h2.Driver}" />
<property name="jdbcUsername" value="${jdbc.username:sa}" />
<property name="jdbcPassword" value="${jdbc.password:}" />
<property name="databaseSchemaUpdate" value="true" />
<property name="strictMode" value="false"/>
</bean>
</beans>
使用此配置时,将首先在 /opt/conf/flowable.properties 文件中查找属性。
支持的数据库
下面列出了 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 驱动测试 |
创建数据库表
Flowable DMN 使用 Liquibase 来跟踪、管理和应用数据库模式变更。
为你的数据库创建数据库表最简单的方式是:
- 将 flowable-dmn-engine JAR 添加到你的 classpath
- 添加合适的数据库驱动
- 将一个 Flowable 配置文件(flowable.dmn.cfg.xml)添加到你的 classpath,指向你的数据库(参见数据库配置章节)
- 执行 DbSchemaCreate 类的 main 方法
数据库表名说明
Flowable DMN 的数据库表名都以 ACT_DMN_ 开头。
- ACT_DMN_DATABASECHANGELOG:Liquibase 使用此表跟踪哪些 changeset 已运行。
- ACT_DMN_DATABASECHANGELOGLOCK:Liquibase 使用此表确保一次只有一个 Liquibase 实例在运行。
- ACT_DMN_DECISION_TABLE:此表包含已部署决策表的元数据。
- ACT_DMN_DEPLOYMENT:此表包含部署元数据。
- ACT_DMN_DEPLOYMENT_RESOURCE:此表包含 DMN 定义资源和元数据。
数据库升级
在运行升级之前,请务必备份你的数据库(使用你的数据库备份功能)。
默认情况下,每次创建流程引擎时都会进行版本检查。这通常在你的应用或 Flowable webapps 启动时发生一次。如果 Flowable 库检测到库版本与 Flowable 数据库表版本之间存在差异,则抛出异常。
要升级,首先要在你的 flowable.dmn.cfg.xml 配置文件中放入以下配置属性:
<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 在首次检测到库与数据库模式不同步时,会自动将数据库模式升级到较新版本。
部署缓存配置
所有决策在解析后都会被缓存,以避免每次需要决策表时都访问数据库,并且因为决策表数据不会改变。默认情况下,此缓存没有限制。要限制 决策缓存,添加以下属性:
<property name="decisionCacheLimit" value="10" />
设置此属性将用一个具有给定硬限制的 LRU 缓存替换默认的 hashmap 缓存。当然,此属性的最佳值取决于所存储的决策总量以及运行时实际使用的决策数量。
你也可以注入自己的缓存实现。它必须是一个实现了 org.flowable.dmn.engine.impl.persistence.deploy.DeploymentCache 接口的 bean:
<property name="decisionCache">
<bean class="org.flowable.MyCache" />
</property>
严格模式
默认情况下,严格模式是启用的。这意味着命中策略将按照 DMN 1.1 规范所述运行。
不过也可以禁用严格模式。
<beans>
<bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
<!-- ... -->
<property name="strictMode" value="false"/>
<!-- ... -->
</bean>
</beans>
其效果是,当违反命中策略约束时,结果不会失效。可能的违规将作为校验消息记录在审计日志中。
自定义 Flowable Function Delegate
Flowable DMN 提供一些内置的 JUEL Function Delegate。通过在 dmnEngineConfiguration bean 上设置 customFlowableFunctionDelegates 属性,你可以提供自己的实现。这些可以在表达式中使用,以执行你自己的逻辑。
<beans>
<bean id="dmnEngineConfiguration" class="org.flowable.dmn.engine.impl.cfg.StandaloneDmnEngineConfiguration">
<!-- ... -->
<property name="customFlowableFunctionDelegates">
<list>
<bean ref="myOwnFunctionDelegateOne" />
<bean ref="myOwnFunctionDelegateTwo" />
</list>
</property>
<!-- ... -->
</bean>
<bean id="myOwnFunctionDelegateOne" class="org.acme.MyOwnFunctionDelegateOne" />
<bean id="myOwnFunctionDelegateTwo" class="org.acme.MyOwnFunctionDelegateTwo" />
</beans>
注意,自定义 Function Delegate 必须继承自 org.flowable.engine.common.impl.el.AbstractFlowableFunctionDelegate。
日志
所有日志(flowable、spring、mybatis 等)都通过 SLF4J 路由,允许你选择自己喜欢的日志实现。
默认情况下,flowable-engine 依赖中不包含 SFL4J 绑定 JAR;要使用你选择的日志框架,应在你的项目中添加它。 如果未添加实现 JAR,SLF4J 将使用 NOP 记录器,除了发出一条将不记录任何内容的警告外,不记录任何内容。有关这些绑定的更多信息,参见 http://www.slf4j.org/codes.html#StaticLoggerBinder。
例如,使用 Maven 时,添加如下依赖(这里使用 log4j),注意你仍需添加版本:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</dependency>
flowable-rest webapp 配置为使用 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 时的示例(省略版本):
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>