jBPM 用户指南(6)

  

作者:jBPM组

版本:5.0.0

原文版权归作者所有,该翻译稿仅供学习交流使用,引用或转载请保证该部分的完整

 

 

7领域(Domain-specific)流程

7.1介绍

7.2示例:通知

7.2.1创建工作事项定义

7.2.2注册工作事项定义

7.2.3在流程中使用新的工作事项

7.2.4调用服务节点

 

 7.1介绍

 

 jBPM的一个目标是允许用户以领域扩展的方法扩展一般流程,以简化在特定应用程序领域的开发。本教程将描述如何朝着领域流程迈出你的第一步。你不需要成为能定义自己的领域节点的jBPM专家,只需要像有jBPM经验的一般开发人员一样考虑集成代码即可。

 

大多数流程语言都提供了一些通用动作(节点)构造器,允许插入定制的用户动作。这些动作通常都位于底层,就需要用户编辑特定的代码来工作。这些代码更接近于某一特定的目标环境,很难在其他不同的上下文环境中复用这些流程。

 

领域语言是针对某一特定应用程序域的,因些能提供与所要解决的问题更接近的构造器。这使得流程更加清晰。我们将展示如何定义领域工作事项(也称为服务节点),它将用来表示所要执行工作的原子单位。这些服务节点指定将在以声明方式提供的流程的上下文中执行的工作。例如,在一个较高层次指定要执行什么(不是如何执行),而隐藏实现细节。

 

所以我们希望服务节点是:

  1. 领域的(Domain-specific)
  2. 可声明的(是什么,非如何)
  3. 位于较高层次(无需编码)
  4. 上下文可定制

用户可以轻松定义自己的领域服务节点并与我们的流程语言集成。下面的图是一个体检流程。这个流程包含的领域服务节点用于要求护士任务(如测量血压),药物处方及通知体检提供者。

 

 

 

7.2 示例:通知

 

让我们开始展示如何包含一个发送通知的简单的工作事项。工作事项是以声明方式表示需要执行工作的原子单位。一般有一个唯一名称及在细节上描述工作的参数,也可以在执行完成后以结果方式返回信息。我们要定义的工作事项包含四个参数,没有返回值。

 

 Name: "Notification"
  Parameters
  From [String]
  To [String]
  Message [String]
  Priority [String]
 

 7.2.1创建工作事项定义

 

 所有的工作事项定义必须指定在位于项目类路径的一个或多个配置文件中,所有的属性要以名-值对的方式指定。参数与返回值需要映射,参数需要与期待的数据类型关联。配置文件中也包含一些附加的用户界面信息,如图标、工作事项的显示名称。(我们使用MVEL读取配置文件,这样可以处理一些高级配置文件)。定义的MyWorkDefinitions.conf文件如下:

 

All wprk definitions must be specified in one or more configuration files in the project classpath, where all the properties are specified as name-value pairs. Parameters and results are maps where each parameter name is also mapped to the expected data type. Note that this configuration file also includes some additional user interface information, like the icon and the display name of the work item. (We use MVEL for reading in the configuration file, which allows us to do more advanced configuration files). Our MyWorkDefinitions.conf file looks like this:

 

 

 

 7.2.2注册工作事项定义

 

可以用配置APIdrools.workDefinitions属性来注册工作事项定义,它表示一个包含所定义工作事项的文件列表(用空格分隔)。 例如在项目的META-INF目录下添加一个drools.rulebase.conf文件,再加入下面的代码:

 

 drools.workDefinitions = MyWorkDefinitions.conf

 

 

7.2.3在流程中使用新的工作事项

 

创建并注册好工作事项之后就可以在流程中使用了。流程编辑器在面板上有一个独立的区域存在这些项目中定义的服务节点。

 

 

 

 

使用拖拽,可以将通知节点加到流程中,在属性视图中可以设置属性值。

 

除了在定制的以外,所有的工作事件都有以下三个属性:

  • Parameter Mapping:参数映射,可以将流程变量的值映射到工作事项的参数中。这样就可以根据流程定义的当前状态定制工作事项(比如通知的优先级可取决于流程的相关信息)。
  • Result Mapping:返回值映射,可以将返回值映射到流程变量中,供流程的后续步骤使用。
  • Wait for completion:默认情况下,流程创建了工作事项,在继续执行前会等待它的完成。也可以把Wait for completion属性设置为"false",这样就不等待立即执行下一步骤。

7.2.4调用服务节点

 

Drools包含一个WorkItemManager对象,负责在需要时执行工作事项。WorkItemManager会把工作事项委托给WorkItemHandler,后者在执行完成时通知WorkItemManager。需要创建一个NotificationWorkItemHandler(实现WorkItemHanlder接口)对象来执行通知工作事项:

 

 

WorkItemHandler用邮件发出一个通知,并且立即告诉WorkItemManager工作事项已经完成。不是所有的工作事项都可以直接完成的。如果是用异步方式执行,会在发出调用后再过若干时间才通知WorkItemManager,这种情况下工作事项有可能在完成之前被结束(取消)了。取消方法中可以指定如何取消工作事项。

 

需要用API向WorkItemManager注册WorkItemHandler:

 

ksession . getWorkItemManager (). registerWorkItemHandler ("Notification", new NotificationWorkItemHandler());
 

分隔开流程与工作事项的执行有以下的好处:

  1. 流程更加支持可声明化,即指定做什么,而不是如何做。
  2. 通过适配工作事项句柄可以适应环境的改变,而不更改流程。这样可以在不同的环境中使用同一流程,要做的只是事项句柄与正确的服务集成而已。
  3. 不同的上下文可以使用不同的事项句柄。譬如在测试或者模拟环境中,根本不需要执行实际的工作事项,此时只需要用一个替代的句柄来测试就行。

 

8持续性

 

8.1运行时(Runtime)状态

8.1.1二进制持续化

8.1.2安全点(Safe Points)

8.1.3配置

8.1.4事务

8.2流程定义

8.3历史日志

8.3.1数据库方式存储流程事件

 

jBPM可以使用持续性存储保存某些信息,如流程实例状态、历史信息等。 

 

8.1运行时(Runtime)状态

 

流程启动时将创建一个流程实例,该实例流程在特定上下文中的执行。譬如执行一个处理销售订单的流程,就要为每个销售人员的请求创建独立的实例。流程实例表示在上下文中的执行状态,包含全部相关信息。要注意的是仅包含可让流程实例持续执行的最小运行状态,而不包含不再需要的历史信息。

 

调度执行流程的运行期状态可以持续化到数据库中,这样可以在发生非预期错误时恢复这些实例的状态,或者可以从内存中移除这些实例在需要时再加载。jBPM允许你使用不同的持续化策略。默认情况下,你不配置引擎,则不执行流程实例的持续化操作。

 

8.1.1二进制持续化(Binary Persistence)

 

jBPM提供了二进制方式的持续化机制,可以将流程实例状态保存到二进制数据集里。这些二进制数据集一般对是比较小的,只包含流程实列最小的执行状态。譬如对于一个简单的流程实例,通常包含一个或多个节点实例,或许还有一些变量值。

 

8.1.2安全点(Safe Points)

 

在流程引擎的执行期所存储的实例状态称为"安全点(safe points)"。流程实例从等待状态开始或继续运行时引擎将作连续的处理,直到不再有更多的动作需要执行,此时引擎到达下一个安全状态,而实例上那些受影响的状态将进行持续性(存储)。

 

8.1.3配置

 

默认情况下,引擎不会对运行期数据进行持续化,在引擎上配置也比较简单,添加一个配置文件,再加入必要的依赖项。持续化本身基于Java Persistence API(JPA)实现,所以可以使用不同的持续化机制。我们默认使用Hibernate,H2是另一个可用的方式,也可以自由选择其他的。

 

首先需要把依赖项加入到类路径中。你如果使用Eclipse IDE,则把jar文件加到Drools的运行目录下,或者手动加到你的项目中。这些依赖项第一个是jbpm-persisstence-jpa.jar,该文件包含保存运行期状态的代码。其次就是其他一些文件,取决于所选的持续化方案及使用的数据库。默认的用Hibernate作为JPA persistence 提供者,H2数据库及Bitronix提供基于JTA的事务管理,这样就需要下面这些附加的依赖项:

  1. jbpm-persistence-jpa (org.jbpm)
  2. drools-persistence-jpa (org.drools)
  3. persistence-api (javax.persistence)
  4. hibernate-entitymanager (org.hibernate)
  5. hibernate-annotations (org.hibernate)
  6. hibernate-commons-annotations (org.hibernate)
  7. hibernate-core (org.hibernate)
  8. dom4j (dom4j)
  9. jta (javax.transaction)
  10. btm (org.codehaus.btm)
  11. javassist (javassist)
  12. slf4j-api (org.slf4j)
  13. slf4j-jdk14 (org.slf4j)
  14. h2 (com.h2database)
  15. commons-collections (commons-collections)

下一步是配置jbpm引擎。最简单的办法是用JPAKnowledgeService创建你自己的基于knowledge base的knowledge 会话,一份knowledge 会话配置(如果需要的话)及环境,环境需要引用你的Entity Manager Factory。举例如下:

 

 

 你也可以用JPAKnowledgeService在会话标识上重新创建一个会话:

 

 

要注意的是只对流程实例执行所需要的最小状态进行保存,那些不再用到的已经执行过的节点的信息,或者已经处理完成或撤消的流程实例不在此列。如果你想要搜索历史信息需要使用历史日志,稍后将会解释。

 

需要在META-INF目录下添加一个持续化配置文件persistence.xml,用Hibernate和H2数据库配置JPA,如下所示。如果更改实现自己的要求,可以参考JPA及Hibernate文档。

  

 

配置文件引用一个名为J"jdbc/processInstanceDS"的数据源。下面的这段Java代码用来建立该数据库,此处用文件方式的H2数据库。

  

 

部署应用程序服务器时通常是在部署目录下放一个配置文件来创建数据源,如: 

  

 

8.1.4 事务

 

如果你没有在应用程序中提供事务边界,引擎执行每个方法在事务上的隔离的。你接受这种结果那就什么都不用做,否则需要自己指定事务边界。比如,可以把多个命令放入同一个事务中。

 

在使用事务之前需要注册事务管理器。下面代码演示使用Bitronix事务管理器。下一步我们使用Java Transaction API(JTA)来指定事务边界,如下:

  

 

8.2流程定义

 

流程定义文件一般以XML格式书写,这些文件开发时在文件系统中存储比较方便。但是想要在多个引擎用knowledge访问,我们还是推荐使用knowledge repository。

 

Gnuvnor做为Drools的子项目正好满足这些。它由一个可以存储多种类型的knowledge的库(repository)组成,不仅可以处理流程定义,还包括规则,对象模型等。用WebDAV或者knowledge代理在创建knowledge base时从Guvnor下载信息并抽取这些knowledge,并且提供了一个Web应用程序允许业务用户查看或者更新这些knowledge 库中的信息。参考Drools Guvnor文档了解更多信息。

 

 

8.3历史日志

 

多数情况下存储流程实例的执行信息是有用的,可以进行历史回溯,比如想知道某一流程实例在执行时做了什么样的动作,或者监控分析某一流程的效率等。在运行时数据库中保存这些历史信息则不可取,引起运行期数据膨张,而且进行监控或者分析查询时也会影响引擎运行的性能,所以要把历史数据单独存放。

 

执行信息的历史日志来源于引擎在执行时产生的事件。 Drools运行引擎提供了侦听这些不同类型事件的通用机制。所需的信息可以方便地从事件中提取然后进行持续化,比如保存到数据库,保存时也可以按照自己的要求进行过滤。

 

8.3.1数据库方式存储流程事件

 

jbpm-bam模块包含一个事件监听器,直接使用JPA或Hibernate在数据库中存储流程相关的信息。数据库包含两张表,一张是流程实例信息,另外一张是节点实例信息(如下):

  1. ProcessInstanceLog: 该列表包含流程实例id,流程(定义)id,开始日期(如果可用的话),结束日期。
  2. NodeInstanceLog: 该表存储流程实例中每一个执行过的节点的详细信息。包括节点通过一个入连接生成实例到通过出连接离开。它存储了对应的流程实例id,流程定义id,节点实例id,节点定义id,还包括事件类型(0=enter,1=exit)及事件日期。

 

 

可以按以下方式处理日志,之前你需要先向会话(或者工作内存)注册日志:

  

 

 

这里的日志跟其他审核日志一样,可以调用方法addFilter添加一个或者多个过滤器,以记录并保存所要信息到数据库中。只有过滤通过的数据才会存储到数据库。当不再需要日志时你可以销毁它。

 

要指定存储日志信息的数据库,可以修改persisstence.xml,如下:

 

 

 

 

这些全部的信息在不同的需求中很容易进行查询、使用,包括为特定的流程实例创建历史日志以分析该类型流程全部实例的性能。

 

这些审核日志只作为默认实现,我们不知道你要什么样的数据用于回溯分析,出于性能的考虑推荐只记录相关的信息。根据具体的需求,你可以定义自己的数据模型记录所要的信息,并用事件监听器来获取这些信息。 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值