问题
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