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.