我在尝试动态重新加载规则时遇到问题。 从上下文开始:我们有DRL文件,其中包含总共10000条规则和各种类型。由于编译和重新部署规则的过程开始很长(超过几分钟),我们希望编译和编译规则。仅重新部署修改后的规则。
要符合DRL标准,我们必须在DRL中声明重新部署修改后的规则和所有使用的类型。
我们的问题是新DRL中声明的类型不会与已部署的类型合并,因此在匹配这些类型时不会激活新规则。
我在查看ReteoRuleBase对象时发现,TypeDeclaration列表包含两个以“Item”命名的类,这肯定是为什么重新部署的规则与正确的对象不匹配。
首先,我的单元测试暴露了我们部署和重新部署的方式:
@Test
public void test_hot_deploy() throws FileNotFoundException {
File drl1 = new File("src/test/resources/essai-drools/hot-deploy-1.drl");
Resource resource1 = ResourceFactory.newInputStreamResource(new FileInputStream(drl1));
File drl2 = new File("src/test/resources/essai-drools/hot-deploy-2.drl");
Resource resource2 = ResourceFactory.newInputStreamResource(new FileInputStream(drl2));
KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
builder.add(resource1, ResourceType.DRL);
KnowledgeBase kb = builder.newKnowledgeBase();
StatefulKnowledgeSession session = kb.newStatefulKnowledgeSession();
int fired = session.fireAllRules();
Assert.assertEquals(2, fired);
System.out.println("--- redeploy ---");
KnowledgeBuilder builder2 = KnowledgeBuilderFactory.newKnowledgeBuilder();
builder2.add(resource2, ResourceType.DRL);
kb.addKnowledgePackages(builder2.getKnowledgePackages());
session = kb.newStatefulKnowledgeSession();
fired = session.fireAllRules();
Assert.assertEquals(2, fired);
}
原始DRL(第一次部署):
package test;
declare Item
value : String
end
rule "insertion"
when
then
Item $item = new Item();
$item.setValue("A");
insert($item);
System.out.println("Object A inserted");
end
rule "modification"
when
$item: Item(value == "A")
then
$item.setValue("B");
update($item);
System.out.println("Object A -> B");
end
重新部署的DRL:
package test;
declare Item
value : String
end
rule "modification"
when
$item : Item(value == "A")
then
$item.setValue("C");
update($item);
System.out.println("Object A -> C");
end
输出:
Object A inserted
Object A -> B
--- redeploy ---
Object A inserted
缺少输出(如您所见,未执行重新部署规则)
Object A -> C
我们如何处理这种不合并的类型?
希望你有一个想法,我在这里只是为了信息。
答案 0 :(得分:1)
从版本5.2开始,Drools不支持重新部署类型声明。原因是在java中,类由classloader + class标识。部署类型声明时,它将需要类加载器刷新,从而有效地创建新的类加载器。正如您所指出的那样,所有现有规则仍然需要旧的类加载器+类,并且不会与新的类加载器+类匹配。
因此,我建议您,如果需要热重新配置规则,请将类型声明保存在单独的DRL文件中,并仅重新部署规则文件。或者,您可以动态生成新规则或从文件中提取已更改的规则,并仅重新部署它们。