jBPM允许某些信息的持久性存储。本章描述了这些不同类型的持久性,以及如何配置它们。存储的信息的一个例子是运行时状态的过程。存储过程运行时状态是必要的,为了能够继续执行流程实例在任何时候,如果出现错误。此外,过程定义本身,和历史信息(日志的当前和以前的进程状态已经)也可以坚持。
每当开始一个过程,一个流程实例被创建时,它表示在特定上下文的执行过程。例如,当执行一个过程,指定如何处理销售订单,一个流程实例为每个销售创建请求。流程实例代表特定上下文的当前执行状态,和包含所有相关信息的流程实例。注意,它只包含运行时状态(最小限度的),需要继续执行,流程实例在后来的一些时间,但它并不包括流程实例的历史信息,如果信息不再需要在流程实例。
执行的运行时状态可以持续的过程,例如,在一个数据库中。这允许恢复执行所有正在运行的进程的状态以防意外的失败,或暂时删除运行实例从记忆和恢复他们在后来的一些时间。jBPM允许您插入不同的持久性策略。默认情况下,如果你不配置流程引擎否则,流程实例并不持久。
如果你配置引擎使用的持久性,它会自动存储运行时状态到数据库中。你不需要触发坚持自己,时,引擎将照顾这个持久性启用。当你调用引擎,它将确保任何更改存储调用结束时,在所谓的安全点。每当出现问题,你恢复从数据库引擎,你也不应该重新加载过程实例和触发手动恢复执行,流程实例将自动恢复执行,如果他们被触发,例如像计时器到期,完成一个任务所要求的流程实例,或一个信号被发送到流程实例。引擎将自动重新加载流程实例。
运行时持久性数据一般应考虑内部,这意味着你可能不应该直接访问这些数据库表,特别是不要直接修改这些(如改变流程实例的运行时状态没有引擎知道可能意想不到的副作用)。在大多数情况下,当前执行流程实例的状态信息是必需的,使用历史日志主要是推荐(见下文)。在某些情况下,它仍然可能是有用的,例如直接查询数据库表的内部,但是你只能这样做如果你知道你正在做什么。
jBPM使用二进制的持久性机制,或称为编组,流程实例的状态转换成二进制数据集。当你使用jBPM持久性,这种机制是用来保存或从数据库中检索流程实例的状态。相同的机制也应用于会话状态和任何工作项的状态。
当流程实例状态保存,会发生两件事情:
首先,流程实例信息转换为二进制blob。由于性能的原因,使用一个自定义的序列化机制,而不是普通的Java序列化。
然后该blob存储,与其他关于此流程实例元数据。这个元数据包括,除其他事项外,流程实例id,进程id,这个过程开始日期。
除了流程实例状态,会话本身也可以存储一些状态,如定时器工作的状态,或会话数据,任何业务规则将被评估。这个会话状态存储分别转换成一个二进制blob,会话的id和一些元数据。你可以随时恢复会话状态通过重载会话与给定id。可以使用检索会话id ksession.getId()。
注意,流程实例二进制数据集通常是相对较小的,因为他们只包含最小的执行流程实例的状态。对于一个简单的流程实例,这通常包含一个或几个节点实例,即。,目前正在执行的任何节点,任何现有的变量值。
由于jBPM使用编组,数据模型是简单的和小:
sessioninfo实体包含的状态(知识)会话的jBPM流程实例正在运行。
Table 8.1. SessionInfo
Field | Description | Nullable |
---|---|---|
id |
主键 | NOT NULL |
lastmodificationdate |
最后一次的实体被保存到数据库 | |
rulesbytearray |
二进制数据集包含会话的状态 | NOT NULL |
startdate |
会议的开始时间 | |
optlock |
版本锁 |
processinstanceinfo实体包含jBPM流程实例的状态。
Table 8.2. ProcessInstanceInfo
Field | Description | Nullable |
---|---|---|
instanceid |
主键 | NOT NULL |
lastmodificationdate |
最后一次的实体被保存到数据库 | |
lastreaddate |
最后一次,从数据库中检索实体(读) | |
processid |
流程的名称 | |
processinstancebytearray |
这是二进制数据集包含流程实例的状态 | NOT NULL |
startdate |
开始时间 | |
state |
一个整数代表流程实例的状态 | NOT NULL |
optlock |
版本锁 |
eventtypes实体包含有关事件,一个流程实例将接受或经历了。
Table 8.3. EventTypes
Field | Description | Nullable |
---|---|---|
instanceid |
这引用processinstanceinfo主键,外键约束本专栏。 | NOT NULL |
eventTypes |
一个文本字段相关过程经历了的一个事件。 |
Table 8.4. WorkItemInfo
Field | Description | Nullable |
---|---|---|
workitemid |
主键 | NOT NULL |
creationDate |
工作项的名称 | |
name |
工作项的名称 | |
processinstanceid |
The (primary key) id of the process: there is no foreign key constraint on this field. | NOT NULL |
state |
状态 | NOT NULL |
optlock |
版本锁 | |
workitembytearay |
这是二进制数据集包含工作项的状态 | NOT NULL |
CorrelationKeyInfo实体包含相关信息的密钥分配给流程实例——松散的关系,因为这表是可选的只有当使用相关功能是必需的。
表8.5。CorrelationKeyInfo
Field | Description | Nullable |
---|---|---|
keyid |
主键 | NOT NULL |
name |
分配的名称 | |
processinstanceid |
The id of the process instance which is assigned to this correlation key | NOT NULL |
optlock |
版本锁 |
CorrelationPropertyInfo实体包含相关信息给相关的属性键分配给流程实例。
Table 8.6. CorrelationPropertyInfo
Field | Description | Nullable |
---|---|---|
propertyid |
主键 | NOT NULL |
name |
名称 | |
value |
值 | NOT NULL |
optlock |
版本锁 | |
correlationKey-keyid |
Foregin key to map to correlation key | NOT NULL |
ContextMappingInfo实体包含上下文信息信息映射到ksession。这是一个内部RuntimeManager的一部分,当不使用RuntimeManager可以被认为是可选的。
Table 8.7. ContextMappingInfo
Field | Description | Nullable |
---|---|---|
mappingid |
主键 | NOT NULL |
context_id |
上下文的标识符 | NOT NULL |
ksession?id |
标识符的ksession映射到这个上下文 | NOT NULL |
optlock |
版本锁 |
流程实例的状态存储在所谓的“安全点”过程的执行引擎。每当一个流程实例执行(例如当它开始或继续从先前的等待状态,发动机执行流程实例,直到没有可以执行更多的操作(即流程实例要么已经完成(或者是流产),或者它已经达到了一个等待状态的并行路径)。在这一点上,引擎已经达到下一个安全状态和流程实例的状态(以及所有其他可能受到影响的流程实例)进行持久存储。
在许多情况下,这将是有用的(如果不是必要的)来存储过程实例的执行信息,以便之后可以使用此信息。例如,有时我们想验证哪些动作已经执行一个特定的流程实例,或在一般情况下,我们希望能够监视和分析一个特定过程的效率。
然而,在运行时数据库中存储历史信息会导致数据库规模迅速增长,更不用说,监测和分析查询可能会影响您的运行时引擎的性能。这就是为什么可以单独存储过程执行历史信息。
这段历史日志执行信息创建基于流程引擎执行期间产生的事件。这是可能的,因为jBPM运行时引擎提供了一个通用的机制听事件。可以很容易地从这些事件中提取必要的信息,然后保存到数据库中。过滤器还可以用来限制登录信息的范围。
jbpm-audit模块包含一个事件侦听器,存储过程相关信息在数据库中使用JPA。数据模型本身包含三个实体,一个流程实例信息,一个节点实例信息,一个(过程)变量实例信息。
Figure 8.2. jBPM Audit data model
ProcessInstanceLog表包含基本的日志信息流程实例。
Table 8.8. ProcessInstanceLog
Field | Description | Nullable |
---|---|---|
id |
主键 | NOT NULL |
duration |
此流程实例的实际期限开始日期以来 | |
end_date |
当适用时,结束日期的流程实例 | |
externalId |
可选的外部标识符用于关联——例如部署一些元素id | |
user_identity |
可选的用户的标识符开始流程实例 | |
outcome |
流程实例的结果,例如错误代码的流程实例是完成错误事件 | |
parentProcessInstanceId |
父进程实例的流程实例id | |
processid |
进程的id | |
processinstanceid |
流程实例的ID | NOT NULL |
processname |
流程的名称 | |
processversion |
流程的版本 | |
start_date |
流程开始日期 | |
status |
状态 |
NodeInstanceLog表包含更多关于哪些节点的信息实际上是在每个流程实例执行。当一个节点实例输入从一个传入的连接或退出通过它的一个对外的连接,这些信息存储在这个表。
Table 8.9. NodeInstanceLog
Field | Description | Nullable |
---|---|---|
id |
主键 | NOT NULL |
connection |
的实际标识符序列流,导致该节点实例 | |
log_date |
事件的日期 | |
externalId |
可选的外部标识符用于关联——例如部署一些元素id | |
nodeid |
流程节点ID | |
nodeinstanceid |
流程实例ID | |
nodename |
节点名称 | |
nodetype |
节点类型 | |
processid |
流程ID | |
processinstanceid |
流程实例ID | NOT NULL |
type |
事件类型 (0 = enter, 1 = exit) | NOT NULL |
workItemId |
可选——只对特定的节点类型,工作项的标识符 |
VariableInstanceLog表包含变量的变化信息的实例。默认时只生成日志条目(后)一个变量变化。也可以日志条目在变量(值)的变化。
Table 8.10. VariableInstanceLog
Field | Description | Nullable |
---|---|---|
id |
主键 | NOT NULL |
externalId |
可选的外部标识符用于关联——例如部署一些元素id | |
log_date |
事件开始时间 | |
processid |
流程ID | |
processinstanceid |
流程实例ID | NOT NULL |
oldvalue |
变量的前一个值的时候,日志 | |
value |
变量的值的时候,日志 | |
variableid |
变量在流程定义id | |
variableinstanceid |
变量在流程实例定义id |
登录过程这样的历史信息数据库中,你需要注册日志记录器会话是这样的:
EntityManagerFactory emf = ...;
StatefulKnowledgeSession ksession = ...;
AbstractAuditLogger auditLogger = AuditLoggerFactory.newJPAInstance(emf);
ksession.addProcessEventListener(auditLogger);
// invoke methods one your session here
指定的数据库应该存储信息,修改文件持久化。persistence.
xml文件包含审计日志类(ProcessInstanceLog,NodeInstanceLog和VariableInstanceLog),如下所示。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence
version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance>
<persistence-unit name="org.jbpm.persistence.jpa" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/jbpm-ds</jta-data-source>
<mapping-file>META-INF/JBPMorm.xml</mapping-file>
<class>org.drools.persistence.info.SessionInfo</class>
<class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
<class>org.drools.persistence.info.WorkItemInfo</class>
<class>org.jbpm.persistence.correlation.CorrelationKeyInfo</class>
<class>org.jbpm.persistence.correlation.CorrelationPropertyInfo</class>
<class>org.jbpm.runtime.manager.impl.jpa.ContextMappingInfo</class>
<class>org.jbpm.process.audit.ProcessInstanceLog</class>
<class>org.jbpm.process.audit.NodeInstanceLog</class>
<class>org.jbpm.process.audit.VariableInstanceLog</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>