Drools 5.1.1_DOC (49)
Drools 5.1.1_DOC_Drools Flow
4.10 更新流程
随 着时间的推移,流程可能演变,例如,因为流程自身需要被改进,或由于不断变化的需求。实际上,你不能真正地更新一个流程,你只能部署一个新版本的流程,而 老版本的流程会仍然存在。这是因为存在的流程实例可能仍然需要那个流程定义。所以,新流程将会有一个不同的id,尽管名字可能是相同的,而且你可以使用版 本参数显示在什么时候一个流程被更新(版本参数只是一个String,而且不能被流程框架验证,所以你可以选择你自己的格式用于次要/主要更新,等等)。
每当一个流程被更新,重要的是要确定对已经运行的流程实例会发生什么。对于每个运行的实例可以考虑以下不同的策略之一:
-
继续:运行的流程实例如遵守它在流程实例启动时被定义的流程(定义)一样正常地继续。因此,已经运行的实例会继续,似乎流程从来没有被更新。 新实例能够使用更新的流程被启动。
-
中断(并重启): 已经运行的实例被中断。如果需要,流程实例可以使用新流程定义被重启。
-
转移:流程实例被迁移到新的流程定义。意味着——一旦它已经被成功迁移——它将根据更新的流程逻辑继续执行。.
默认时,Drools流使用继续(proceed)方法,意味着可以部署相同流程的多个版本,但是存在的流程实例会根据在启动该流程实例时使用的流程定义继续执行。当然,使用流程管理API,运行的流程实例也总是可以被中断的。流程实例迁移是更困难的,在随后段落中解释。
4.10.1 流程实例的迁移
一 个流程实例包含需要在稍后的某些适时时间点继续执行的所有运行时信息。它包括链接到这个流程实例的所有数据(用变量),而且包括在该流程图中的当前状态。 对于当前活动的每个节点,都用一个节点实例来表示它。 这个节点实例也可能包含链接到那个单独特殊节点执行的附加状态。对于每种节点的类型,也有一个不同节点实例的类型。
一个流程实例只包含 运行时状态,并且被链接到一个特殊的流程(非直接,使用id引用)——其代表在执行这个流程实例时需要被遵守的流程逻辑(这种清晰的定义和运行时状态的分 离,允许重用横跨所有基于这个流程和最小化运行时状态的流程实例的定义)。因此,更新一个运行流程实例为一个新的版本,那么它使用新流程逻辑,而不是旧的 那个,就成了一个简单的问题,改变引用的流程id ,从旧的成为新的id即可。
然而,这样做没有考虑到流程实例(变量实例和节点实例) 的状态也可能需要被迁移。在这种情况下,流程在那儿只是被扩展,而且所有现有的等待状态被保持, 这是相当简单的,流程实例的运行时状态完全不需要被改变。但是,也可能需要一个更复杂的映射。例如,当一个现有的等待状态被删除,或者分裂为多个等待状态 时,一个等待那个状态的存在的流程实例就不能被简单地更新。或者当一个新的流程变量被引入时,那个变量可能需要被正确地被初始化,以便于它可以被用于(被 更新的)流程的其余部分中。
WorkflowProcessInstanceUpgrader 可以被用来更新一个工作流流程为一个新流程实例。当然,你需要提供流程实例,以及新流程的id。默认时,Drools Flow 会使用相同的id自动映射旧(唯一的)节点实例为新节点实例。在使用复合节点时,唯一的节点id是优于它的父节点id(在中间有一个冒号?)的节点id, 用于唯一地识别一个节点(因为在它的节点容器内部的一个节点id是唯一的)。新节点id只是在该节点容器内的新节点id(所以在这儿无唯一节点,只是新节 点id)。以下的代码片断显示了一个简单的例子。
// create the session and start the process "com.sample.ruleflow"
KnowledgeBuilder kbuilder = ...
StatefulKnowledgeSession ksession = ...
ProcessInstance processInstance = ksession.startProcess("com.sample.ruleflow");
// add a new version of the process "com.sample.ruleflow2"
kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(..., ResourceType.DRF);
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
// migrate process instance to new version
Map<String, Long> mapping = new HashMap<String, Long>();
// top level node 2 is mapped to a new node with id 3
mapping.put("2", 3L);
// node 2, which is part of composite node 5, is mapped to a new node with id 4
mapping.put("5.2", 4L);
WorkflowProcessInstanceUpgrader.upgradeProcessInstance(ksession, processInstance.getId(), "com.sample.ruleflow2", mapping);
如果这种类型的映射仍然不满足,你可以为特殊情况描述你自己的定制映射。首先确保断开了流程实例,相应地改变状态,然后重新连接流程实例,类似于WorkflowProcessinstanceUpgrader做它。
4.11 分配规则到一个规则流组
Drools已经提供了一些功能,用于定义规则应该被执行的顺序,如优先级,活动组,等等。在可能处理许多大型规则集时,管理被计算的规则的顺序可以变得复杂。
规则流允许你使用一个流程图指定应该被计算的规则集的顺序。这允许你定义规则集应该依次或并行被计算,允许你指定应该被计算的规则集所根据的条件。本章包含一些规则流例子。
规则流(ruleflow)是规则引擎采取的一系列步骤的一个图形描述,在那儿顺序是重要的。 规则流也能够处理条件分枝、并行和同步。
要使用规则流描述应该被计算的规则的顺序,你首先应该使用ruleflow-group规则属性(在GUI中的"options" )分组规则到规则流组。
然后你应该通过指定应该被计算的ruleflow-groups 的顺序,创建一个以图形方式描述应该被考虑的规则的顺序的规则流图(它是一个流程图)。
rule 'YourRule'
ruleflow-group 'group1'
when
...
then
...
end
这个规则属于名为"group1"的规则流组。
作为规则流组部分被执行的规则由一个流程触发,也可以在规则的推论中访问流程上下文。通过流程上下文件、流程实例或节点实例,可以访问触发的规则流组,或者可以设置或检索变量,例如:
drools.getContext(ProcessContext.class).getProcessInstance()
4.12. 一个简单的规则流(Ruleflow)
上面的规则流指定组"Check Order"中的规则必须在组"Process Order"中的规则之前被执行。这意味着首先只会考虑使用规则流组"Check Order"标记的规则,然后,
只有在没有任何这些规则后,才会考虑"Process Order"的规则。就是这样的了。使用优先级(salience)你也可以取得相似的结果,但是维护更困难,并且让时间关系隐藏在规则或议程组中。
然而,使用规则流组让处理顺序为显式的,在规则结构顶上的一层中,所以管理更复杂情形变得更容易。
在实际中,如果你使用规则流,你有可能比设置一个简单的组进行顺序要做得更多。为模拟流程的分枝,你会使用Split和Join
上面的流是一个更复杂的例子,代表一个处理保险索赔的规则流。最初处理索赔数据验证规则,检查数据的完整性、一致性和完整性。接下
上面的流是一个更复杂的例子,代表一个处理保险索赔的规则流。最初处理索赔数据验证规则,检查数据的完整性、一致性和完整性。接下
要编辑Split节点,你点击该节点,会显示给你一个如上所示的属性面板。然后你必须选类型:AND、OR、和XOR。如果你选择了OR,那么split的任何“输出”都可能发生,
所以处理可以沿着两个或多个路径并行处理。如果你选择了XOR,那么只有一个路径被选择。
如果你选择了OR或XOR,在"Constraints(约束)" 行的右手边会有一个方型按钮。点击这个按钮会打开约束编辑器,
选择你想设置约束的输出路径(例如,Autosettlement),然后你应该看到如下的约束编辑器:
这是一个文本编辑器,在这儿输入约束——它就象一个规则的条件部分。这些约束控制在工作内存中的实事。在上面的例子中,检查值小于250的索赔(claims)。这个条件为true,那么会跟随相关联的路径。
4.13. 使用Drools 4.x规则流程
在Drools4中使用的XML格式存储规则流程,是使用XStream自动产生的。所以,对于人类读者是难以阅读,并且难以管理和扩展。 新创建的Drools流XML格式已经简化了它。但是这意味着,默认时,
旧版的规则流程不能在Drools5引擎中简化执行。
然而我们提供了一个规则流迁移器,允许你转换你旧的.rf文件为新的格式。它使用了一个XSLT转换,根据旧内容转换成新的XML。在你升级Drools4.x为Drools5.x时,你可以使用这个类,
手动一次性转换你的老流程到新的格式。然而,
你也可以在加载它们到知识库时,让KnowledgeBuilder自动升级你的流程为新的格式。虽然每次加载流程到知识库时需要一个转换,但是它支持更无缝的升级。
要制定这种自动升级,你需要设置"drools.ruleflow.port"系统属性为"true",
例如,在启动你的应用程序时,通过增加
-Ddrools.ruleflow.port=true,或者调用
System.setProperty("drools.ruleflow.port", "true")。
Drools Eclipse插件也自动侦听是否打开了一个旧的规则流文件。在这点上时,它将自动处理转换,并显示结果在图形编辑