How to dynamically reload rules using already declared fact types?

限于喜欢 提交于 2019-12-08 09:58:35

问题


I am facing an issue while trying to reload rules dynamically. Starting with the context : we have DRLs files which contains a total of 10000 rules, and various types. As the process of compiling and redeploying rules is starting to be long (over than a couple of minutes), we would like to compile & redeploy ONLY the modified rule.

To be DRL-compliant, we have to declare in the DRL to redeploy the modified rule, AND all used types.

Our problem is that types declared in the new DRL are not merged with types already deployed, so new rules do not activate when matching those types.

I found while looking at the ReteoRuleBase object that the list of TypeDeclaration contains two class named after "Item", and that's surely why the redeployed rule did not match the right object.

First, my unit test exposing the way we deploy and redeploy :

    @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);
}

The original DRL (the first deployed) :

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

The redeployed 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

The output :

Object A inserted
Object A -> B
--- redeploy ---
Object A inserted

The missing output (as you see, the redeploy rule was not executed)

Object A -> C

Any idea of how we could deal with this type which do not merge ?

Hope you got an idea, I am here for mere informations.


回答1:


As of version 5.2, Drools does not support redeployment of type declarations. The reason is that in java, a class is identified by classloader+class. When a type declaration is deployed, it will require a classloader refresh, creating effectively a new classloader. As you've noted, all existing rules will still expect the old classloader+class and will not match the new classloader+class.

So, my suggestion for you is, if you need to hot-redeploy rules, to keep your type declarations in a separate DRL file and only redeploy the rules files. Alternatively, you can generate the new rules on the fly or extract the changed rules from a file and only redeploy them.



来源:https://stackoverflow.com/questions/7081187/how-to-dynamically-reload-rules-using-already-declared-fact-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!