Search code examples
javanullpointerexceptiondroolsrule-enginedrools-fusion

Null pointer exception with Drools accumulate()


I am trying to execute a very basic example demonstrating the use of the accumulate() function of Drools, but am getting a java.lang.NullPointerException exception.

Here is the code:

Metric.java:

package com.sample;

public class Metric
{
  public String id;
  public double value;

  public Metric(String id, double value)
  {
    this.id = id;
    this.value = value;
  }
}

ruleFile1.drl:

package com.sample

declare Metric
    @role( event )
end

rule "rule1"
when
    Metric()
    metricAverage: Number() from accumulate(
        Metric( $value : value ),
        average( $value ) )
then
    System.out.println("metric value average " + metricAverage);
end

KSessionGenerator.java:

package com.sample;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import org.kie.api.KieBase;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class KSessionGenerator {

  public KieSession buildKSession(String ruleFilePath){
    KieServices kieServices = KieServices.Factory.get();

    FileInputStream fis = null;
    try {
      fis = new FileInputStream(ruleFilePath);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      return null;
    }

    String virtualRuleFilePath = "src/main/resources/ruleFile1.drl";
    KieFileSystem kfs = kieServices.newKieFileSystem();
    kfs.write(virtualRuleFilePath, kieServices.getResources().newInputStreamResource(fis));

    KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
    Results results = kieBuilder.getResults();
    if (results.hasMessages(Message.Level.ERROR)) {
      System.out.println(results.getMessages());
      throw new IllegalStateException("### errors ###");
    }

    KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());

    // Change the engine mode to 'stream'
    KieBaseConfiguration config = kieServices.newKieBaseConfiguration();
    config.setOption( EventProcessingOption.STREAM );

    KieBase kieBase = kieContainer.newKieBase( config );
    KieSession kSession = kieBase.newKieSession();

    return kSession;
  }
}

DroolsTest1.java:

package com.sample;

import org.kie.api.runtime.KieSession;

public class DroolsTest1 {

  public static final void main(String[] args) {
    try {
      String ruleFilePath = "src/main/resources/rules/ruleFile1.drl";
      KieSession kSession = (new KSessionGenerator()).buildKSession(ruleFilePath);

      // go !
      Metric metric1 = new Metric("m1", 50);
      Metric metric2 = new Metric("m2", 60);

      kSession.insert(metric1);
      kSession.insert(metric2);

      System.out.println("Firing all rules ...");
      kSession.fireAllRules();
      System.out.println("Rules fired!");

      System.out.println("Bye");
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }
}

kmodule.xml:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="ksession-rules"/>
    </kbase>
</kmodule>

The full stack trace of the exception:

Firing all rules ...
java.lang.RuntimeException: java.lang.NullPointerException
  at org.drools.core.rule.SingleAccumulate.accumulate(SingleAccumulate.java:90)
  at org.drools.core.phreak.PhreakAccumulateNode.addMatch(PhreakAccumulateNode.java:759)
  at org.drools.core.phreak.PhreakAccumulateNode.doLeftInserts(PhreakAccumulateNode.java:163)
  at org.drools.core.phreak.PhreakAccumulateNode.doNode(PhreakAccumulateNode.java:80)
  at org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:562)
  at org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:533)
  at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:334)
  at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:161)
  at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:116)
  at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:235)
  at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:106)
  at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1016)
  at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1302)
  at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1289)
  at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1262)
  at com.sample.DroolsTest1.main(DroolsTest1.java:20)
Caused by: java.lang.NullPointerException
  at org.drools.core.rule.Declaration.getValue(Declaration.java:228)
  at com.sample.Rule_rule11017979978AccumulateExpression0Invoker.evaluate(Rule_rule11017979978AccumulateExpression0Invoker.java:19)
  at org.drools.core.base.accumulators.JavaAccumulatorFunctionExecutor.accumulate(JavaAccumulatorFunctionExecutor.java:109)
  at org.drools.core.rule.SingleAccumulate.accumulate(SingleAccumulate.java:82)
  ... 15 more

I am using Drools version 6.2.0 Final via plugin on Eclipse Mars 4.5.2

Can anyone tell me the cause of the error along with its solution ?


Solution

  • Tried the code, the NPE is caused by

    "$value" -> "Method threw 'java.lang.NullPointerException' exception. 
    Cannot evaluate org.drools.core.rule.Declaration.toString()"
    

    This is due to the Metric class not having any getter methods for its fields. Add the getters and the code will execute without problems