Hi all,
I am using Drools-Fusion v5.4.0.Final. My use case is to add rules
dynamically at runtime which should get automatically updated in the
KnowledgeSession. Rules in my application are defined as DTO. I have
written a toDrl() method which returns a String which essentially is a rule
in drl. I use following code to add it to the already running instance of
rule engine.
*Initialize Rule Engine
*KnowledgeBuilder kBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
if(kBase != null){
kBase.addKnowledgePackages(kBuilder.getKnowledgePackages());
}
// Populate rules from DB
List<AlertDefinitionDto> alertDefs = getDbRules();
for(AlertDefinitionDto alertDef : alertDefs) {
addRule(alertDef);
}
StatefulKnowledgeSession kSession = kBase.newStatefulKnowledgeSession();
*Add Rule
* try {
rwl.lock();
// Create new rule from AlertDefinitionDto
kBuilder.add(org.drools.io.ResourceFactory.newByteArrayResource(alertDef.toDrl().getBytes()),
org.drools.builder.ResourceType.DRL);
if(kBuilder.hasErrors()) {
kBuilder.undo();
KnowledgeBuilderErrors errs = kBuilder.getErrors();
System.err.print(AlertGenerationServiceImpl.class, "Error
adding rule : "+alertDef.getName());
String errorStr = "";
for (KnowledgeBuilderError error : errs) {
errorStr = errorStr + error.getMessage()+"\\n";
}
System.err.print("Error adding new rule: "+errorStr);
}
} finally {
rwl.unlock();
}
*
*
* *// No errors. Update KnowledgeBase.
try {
Collection<KnowledgePackage> kPkgs =
kBuilder.getKnowledgePackages();
kBase.addKnowledgePackages(kPkgs);
} catch (RuntimeException e) {
if(kBase.getRule(RULE_PACKAGE_NAME, alertDef.getName()) !=
null) {
kBuilder.undo();
}
e.printStackStrace();
}
*
*
*Fire Rules
*
* *LogMessage logMsg = getLog();*
*
kSession.insert(logMsg);
kSession.fireAllRules();
This code works fine under all conditions for initialization where rules
are fetched from DB and rule engine is initialized.
The code fails to add new rule dynamically, when the rule engine is already
initialized and fired few number of times with LogMessage as fact. The
errors which I am getting are
------------------------------------------------------------------
1. For the first time when it fails to add new rule.
------------------------------------------------------------------
java.lang.RuntimeException: Null accessor on node: null
at
org.drools.rule.constraint.ConditionAnalyzer.analyzeNode(ConditionAnalyzer.java:229)
at
org.drools.rule.constraint.ConditionAnalyzer.analyzeSingleCondition(ConditionAnalyzer.java:126)
at
org.drools.rule.constraint.ConditionAnalyzer.analyzeCondition(ConditionAnalyzer.java:102)
at
org.drools.rule.constraint.ConditionAnalyzer.analyzeCombinedCondition(ConditionAnalyzer.java:134)
at
org.drools.rule.constraint.ConditionAnalyzer.analyzeCondition(ConditionAnalyzer.java:94)
at
org.drools.rule.constraint.ConditionAnalyzer.analyzeCondition(ConditionAnalyzer.java:73)
at
org.drools.rule.constraint.MvelConditionEvaluator.getAnalyzedCondition(MvelConditionEvaluator.java:78)
at
org.drools.rule.constraint.MvelConstraint.getListenedPropertyMask(MvelConstraint.java:273)
at org.drools.reteoo.AlphaNode.calculateDeclaredMask(AlphaNode.java:372)
at org.drools.reteoo.ObjectSource.initDeclaredMask(ObjectSource.java:151)
at org.drools.reteoo.AlphaNode.<init>(AlphaNode.java:86)
at
org.drools.reteoo.builder.PatternBuilder.attachAlphaNodes(PatternBuilder.java:323)
at
org.drools.reteoo.builder.PatternBuilder.attachPattern(PatternBuilder.java:162)
at org.drools.reteoo.builder.PatternBuilder.build(PatternBuilder.java:80)
at
org.drools.reteoo.builder.GroupElementBuilder$AndBuilder.build(GroupElementBuilder.java:113)
at
org.drools.reteoo.builder.GroupElementBuilder.build(GroupElementBuilder.java:71)
at
org.drools.reteoo.builder.ReteooRuleBuilder.addSubRule(ReteooRuleBuilder.java:155)
at
org.drools.reteoo.builder.ReteooRuleBuilder.addRule(ReteooRuleBuilder.java:128)
at org.drools.reteoo.ReteooBuilder.addRule(ReteooBuilder.java:116)
at org.drools.reteoo.ReteooRuleBase.addRule(ReteooRuleBase.java:445)
at org.drools.common.AbstractRuleBase.addRule(AbstractRuleBase.java:956)
at org.drools.common.AbstractRuleBase.addPackages(AbstractRuleBase.java:627)
at org.drools.reteoo.ReteooRuleBase.addPackages(ReteooRuleBase.java:472)
at
org.drools.impl.KnowledgeBaseImpl.addKnowledgePackages(KnowledgeBaseImpl.java:150)
------------------------------------------------------------------
2. Everytime after 1st failure.
------------------------------------------------------------------
java.lang.NullPointerException
at org.drools.reteoo.ReteooBuilder.removeRule(ReteooBuilder.java:259)
at org.drools.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:459)
at org.drools.common.AbstractRuleBase.removeRule(AbstractRuleBase.java:1107)
at
org.drools.common.AbstractRuleBase.mergePackage(AbstractRuleBase.java:851)
at org.drools.common.AbstractRuleBase.addPackages(AbstractRuleBase.java:610)
at org.drools.reteoo.ReteooRuleBase.addPackages(ReteooRuleBase.java:472)
at
org.drools.impl.KnowledgeBaseImpl.addKnowledgePackages(KnowledgeBaseImpl.java:150)
I have checked numerous times the generated drl (from method toDrl()) is
syntactically correct. The LogMessage has some null fields but they are
checked appropriately in the rules.
I am not sure what is going wrong here. May be the stacktrace provided
above give some pointers to the problem.
Also, please confirm if this is the right way to update rules dynamically.
I have taken a look at KnowledgeAgent but that requires a changeset
represented in XML which I do not have currently in my implementation.
Awaiting response.