Uploaded image for project: 'Drools'
  1. Drools
  2. DROOLS-613

JBRULES-3723 NullPointerException in RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:271)

    XMLWordPrintable

Details

    • Bug
    • Resolution: Cannot Reproduce
    • Major
    • None
    • 6.0.1.Final, 6.1.0.Final
    • None

    Description

      when there is one rule in KBase, dynamically add second rule and fire it. drools report this error:

      Exception stack
      java.lang.NullPointerException
      	at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:271)
      	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:216)
      	at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:91)
      	at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:964)
      	at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1234)
      	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1239)
      	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1222)
      	at mock.com.camel.drools.expert.sample.service.DynamicAddRuleBugTest.testReproduceBugWithSDO(DynamicAddRuleBugTest.java:134)
      

      That two drl rules are almost same expect package name:

      drl 1
      package com.camel.drools.expert.sample.testbug1
      
      import mock.com.camel.drools.expert.sample.service.domain.Order;
      import mock.com.camel.drools.expert.sample.service.domain.RuleConditionSdo;
      
      rule "order flow"
      when
          $rcs:RuleConditionSdo($rc:ruleCondition)
          $order:Order(price>$rc.getDouble("minPrice"), source==$rc.getString("source"), dest==$rc.getString("dest"))
      then
          System.out.println("finished rule for bug test 1" + $rc.getString("source"));
      end
      
      drl 2
      package com.camel.drools.expert.sample.testbug2
      
      import mock.com.camel.drools.expert.sample.service.domain.Order;
      import mock.com.camel.drools.expert.sample.service.domain.RuleConditionSdo;
      
      rule "order flow"
      when
          $rcs:RuleConditionSdo($rc:ruleCondition)
          $order:Order(price>$rc.getDouble("minPrice"), source==$rc.getString("source"), dest==$rc.getString("dest"))
      then
          System.out.println("finished rule for bug test 2" + $rc.getString("source"));
      end
      

      1. The RuleConditionSdo object was dynamically created at runtime, it using a SDO technic. This works failed
      2. If changed RuleCondtionSdo with a pre-write pojo, It works fine.
      3. If use Cglib util net.sf.cglib.beans.BeanGenerator creat RuleConditionSdo object dynamically. It works still fine.

      so, It's like a bug with SDO object.

      Test code below:

      DynamicAddRuleBugTest.java
      package mock.com.camel.drools.expert.sample.service;
      
      import java.io.IOException;
      import java.io.InputStreamReader;
      import java.io.Reader;
      import java.util.HashMap;
      import java.util.Map;
      
      import mock.com.camel.drools.expert.sample.service.domain.Order;
      import mock.com.camel.drools.expert.sample.service.domain.RuleCondition;
      import mock.com.camel.drools.expert.sample.service.domain.RuleConditionSdo;
      
      import org.drools.compiler.builder.impl.KnowledgeBuilderImpl;
      import org.drools.compiler.compiler.DroolsParserException;
      import org.drools.core.impl.InternalKnowledgeBase;
      import org.junit.After;
      import org.junit.Before;
      import org.junit.Test;
      import org.kie.api.runtime.KieSession;
      import org.kie.api.runtime.rule.AgendaFilter;
      import org.kie.api.runtime.rule.Match;
      import org.kie.internal.KnowledgeBaseFactory;
      
      import com.camel.drools.expert.sample.utils.CglibDynamicBeanGenerator;
      import com.camel.drools.expert.sample.utils.RegisterSDOXsd;
      
      /**
       * reproduce dynamic add rule bug
       * @author dengqb
       * @date 2014年9月19日
       */
      public class DynamicAddRuleBugTest {
      
          /**
           * @throws java.lang.Exception
           */
          @Before
          public void setUp() throws Exception {
          }
      
          /**
           * @throws java.lang.Exception
           */
          @After
          public void tearDown() throws Exception {
          }
      
          /**
           * using pre-write RuleCondition Object
           * result: fine
           */
          @Test
          public void testReproduceBug() {
              InternalKnowledgeBase kBase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase();
              String drlFile = "/drools/drl/bug_test1.drl";
              loadPackageFromDrl(kBase, drlFile);
              
              Order order = new Order(50,"ebay","china");
              RuleCondition ruleCondition = new RuleCondition(30,"ebay","china");
              
              KieSession kieSession = kBase.newStatefulKnowledgeSession();
              kieSession.insert(ruleCondition);
              kieSession.insert(order);
              kieSession.fireAllRules(new AgendaFilter(){
                  @Override
                  public boolean accept(Match match) {
                      return match.getRule().getPackageName().endsWith("testbug1");
                  }
              });
              //statfull session使用后必需调用dispose
              kieSession.dispose();
              
              System.out.println("========add new rule=================");
              String drlFile2 = "/drools/drl/bug_test2.drl";
              loadPackageFromDrl(kBase, drlFile2);
              
              kieSession = kBase.newStatefulKnowledgeSession();
              Order order2 = new Order(32.0,"ebay","brazil");
              RuleCondition ruleCondition2 = new RuleCondition(30,"ebay","brazil");
              kieSession.insert(ruleCondition2);
              kieSession.insert(order2);
              kieSession.fireAllRules(new AgendaFilter(){
                  @Override
                  public boolean accept(Match match) {
                      return match.getRule().getPackageName().endsWith("testbug2");
                  }
              });
              kieSession.dispose();
          }
      
          /**
           * using a RuleConditonSdo object, it is dynamically created by SDO technic
           * result: false
           */
          @Test
          public void testReproduceBugWithSDO() {
              InternalKnowledgeBase kBase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase();
              String drlFile = "/drools/drl/bug_sdo_test1.drl";
              loadPackageFromDrl(kBase, drlFile);
              
              Order order = new Order(50,"ebay","china");
              
            //注册sdo对象
              RegisterSDOXsd register = new RegisterSDOXsd();
              register.setXsdFilePath("/drools/xsd/xsdList.txt");
              register.register();
              
              RuleConditionSdo rcsdo = new RuleConditionSdo();
              rcsdo.getRuleCondition().setDouble("minPrice",30);
              rcsdo.getRuleCondition().setString("source","ebay");
              rcsdo.getRuleCondition().setString("dest","china");
              
              KieSession kieSession = kBase.newStatefulKnowledgeSession();
              kieSession.insert(rcsdo);
              kieSession.insert(order);
              kieSession.fireAllRules(new AgendaFilter(){
                  @Override
                  public boolean accept(Match match) {
                      return match.getRule().getPackageName().endsWith("testbug1");
                  }
              });
              //statfull session使用后必需调用dispose
              kieSession.dispose();
              
              System.out.println("========add new rule=================");
              String drlFile2 = "/drools/drl/bug_sdo_test2.drl";
              loadPackageFromDrl(kBase, drlFile2);
              
              kieSession = kBase.newStatefulKnowledgeSession();
              Order order2 = new Order(32.0,"ebay","brazil");
              //RuleCondition ruleCondition2 = new RuleCondition(30,"ebay","brazil");
              RuleConditionSdo rcsdo2 = new RuleConditionSdo();
              rcsdo.getRuleCondition().setDouble("minPrice",30);
              rcsdo.getRuleCondition().setString("source","ebay");
              rcsdo.getRuleCondition().setString("dest","breazil");
              kieSession.insert(rcsdo2);
              kieSession.insert(order2);
              kieSession.fireAllRules(new AgendaFilter(){
                  @Override
                  public boolean accept(Match match) {
                      return match.getRule().getPackageName().endsWith("testbug2");
                  }
              });
              kieSession.dispose();
          }
          
          /**
           * using a dynamicl RuleCondition object, it created by cglib BeanGenerator
           * result: fine
           * @throws ClassNotFoundException
           */
          @Test
          public void testReproduceBugWithDynamicBean() throws ClassNotFoundException{
              InternalKnowledgeBase kBase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase();
              String drlFile = "/drools/drl/bug_dyb_test1.drl";
              loadPackageFromDrl(kBase, drlFile);
              
              Order order = new Order(50,"ebay","china");
              
              Map<String,Class<?>> properties = new HashMap<String,Class<?>>();
              properties.put("minPrice", Class.forName("java.lang.Double"));  
              properties.put("source", Class.forName("java.lang.String"));  
              properties.put("dest", Class.forName("java.lang.String"));  
              // 生成动态 Bean  
              CglibDynamicBeanGenerator ruleCondition = new CglibDynamicBeanGenerator(properties);
              ruleCondition.setValue("minPrice", 40d);
              ruleCondition.setValue("source", "ebay");
              ruleCondition.setValue("dest", "china");
              
              KieSession kieSession = kBase.newStatefulKnowledgeSession();
              kieSession.insert(ruleCondition);
              kieSession.insert(order);
              kieSession.fireAllRules(new AgendaFilter(){
                  @Override
                  public boolean accept(Match match) {
                      return match.getRule().getPackageName().endsWith("testbug1");
                  }
              });
              //statfull session使用后必需调用dispose
              kieSession.dispose();
              
              System.out.println("========add new rule=================");
              String drlFile2 = "/drools/drl/bug_dyb_test2.drl";
              loadPackageFromDrl(kBase, drlFile2);
              
              kieSession = kBase.newStatefulKnowledgeSession();
              Order order2 = new Order(32.0,"ebay","brazil");
              
              ruleCondition = new CglibDynamicBeanGenerator(properties);
              ruleCondition.setValue("minPrice", 30d);
              ruleCondition.setValue("source", "ebay");
              ruleCondition.setValue("dest", "brazil");
              
              kieSession.insert(ruleCondition);
              kieSession.insert(order2);
              kieSession.fireAllRules(new AgendaFilter(){
                  @Override
                  public boolean accept(Match match) {
                      return match.getRule().getPackageName().endsWith("testbug2");
                  }
              });
              kieSession.dispose();
          }
          private void loadPackageFromDrl(InternalKnowledgeBase kBase, String drlFile) {
              final Reader drlReader = new InputStreamReader(this.getClass().getResourceAsStream(drlFile));
              
              final KnowledgeBuilderImpl builder = new KnowledgeBuilderImpl();
              try {
                  builder.addPackageFromDrl(drlReader);
                  if (builder.hasErrors()){
                      System.out.println(builder.getErrors());
                  }
                  kBase.addPackage(builder.getPackage());
              } catch (DroolsParserException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      

      SDO RuleCondition class

      package mock.com.camel.drools.expert.sample.service.domain;
      
      import commonj.sdo.DataObject;
      import commonj.sdo.helper.DataFactory;
      
      /**
       * 
       * @author dengqb
       * @date 2014年9月19日
       */
      public class RuleConditionSdo {
          private DataObject ruleCondition;
          
          public RuleConditionSdo(){
              ruleCondition = DataFactory.INSTANCE.create("http://drools.research.com/xsd/RuleCondition", "RuleCondition");
          }
      
          public DataObject getRuleCondition() {
              return ruleCondition;
          }
      
          public void setRuleCondition(DataObject ruleCondition) {
              this.ruleCondition = ruleCondition;
          }
      }
      
      

      Attachments

        Activity

          People

            mfusco@redhat.com Mario Fusco
            cameldeng_jira qibiao deng (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: