Uploaded image for project: 'JBRULES'
  1. JBRULES
  2. JBRULES-3659

matches operator on variable cause intermittent thread fork and throws exception

This issue belongs to an archived project. You can view it, but you can't modify it. Learn more

    XMLWordPrintable

Details

    • Hide

      The java code that does this multiple insertion and firing is like this:

      Main.java
      package drools;
      
      import org.drools.KnowledgeBase;
      import org.drools.KnowledgeBaseFactory;
      import org.drools.builder.KnowledgeBuilder;
      import org.drools.builder.KnowledgeBuilderFactory;
      import org.drools.builder.ResourceType;
      import org.drools.definition.KnowledgePackage;
      import org.drools.event.rule.DebugWorkingMemoryEventListener;
      import org.drools.io.ResourceFactory;
      import org.drools.runtime.StatefulKnowledgeSession;
      
      import java.util.Collection;
      
      public class Main {
      
          static StatefulKnowledgeSession ksession;
      
          public static void main(String[] argv) throws Exception {
              initRules();
      
              // fire once to run the no condition LHS
              ksession.fireAllRules();
      
              for (int i=0;i < 100; i++) {
              Person person = new Person();
              person.setName("Test");
              ksession.insert(person);
              ksession.fireAllRules();
              }
      
          }
      
          private static void initRules() {
              KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
      
      		// this will parse and compile in one step
      		kbuilder.add(ResourceFactory.newClassPathResource("main.drl", Main.class), ResourceType.DRL);
      
      		// Check the builder for errors
      		if (kbuilder.hasErrors()) {
      			System.out.println(kbuilder.getErrors().toString());
      			throw new RuntimeException("Unable to compile \"main.drl\".");
      		}
      
      		// get the compiled packages (which are serializable)
      		Collection<KnowledgePackage> pkgs = kbuilder
      				.getKnowledgePackages();
      
      		// add the packages to a knowledgebase (deploy the knowledge packages).
      	    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
      		kbase.addKnowledgePackages(pkgs);
      
      		ksession = kbase.newStatefulKnowledgeSession();
      
      		ksession.addEventListener(new DebugWorkingMemoryEventListener());
          }
      
      }
      
      

      The Person is a simple POJO

      Person.java
      public class Person {
      
          private String name;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      

      The rule file that does the matching is like this:

      main.drl
      package drools;
      
      dialect "mvel"
      
      declare Stuff
      	regexp : String
      end
      
      rule "Test Regex"
      	salience 100
          when
          then
          	Stuff s = new Stuff("Test")
              System.out.println("Insert reg ex variable");
              insert (s);
      end
      
      rule "Test Equality"
      	salience 10
          when
          	Stuff( $regexp : regexp )
              Person( name matches $regexp )
              //Person( name matches "Test" )
          then
              System.out.println("Found name");
      end
      
      rule "Dump person"
          when
              $p : Person( )
          then
              retract ( $p )
      end
      
      Show
      The java code that does this multiple insertion and firing is like this: Main.java package drools; import org.drools.KnowledgeBase; import org.drools.KnowledgeBaseFactory; import org.drools.builder.KnowledgeBuilder; import org.drools.builder.KnowledgeBuilderFactory; import org.drools.builder.ResourceType; import org.drools.definition.KnowledgePackage; import org.drools.event.rule.DebugWorkingMemoryEventListener; import org.drools.io.ResourceFactory; import org.drools.runtime.StatefulKnowledgeSession; import java.util.Collection; public class Main { static StatefulKnowledgeSession ksession; public static void main( String [] argv) throws Exception { initRules(); // fire once to run the no condition LHS ksession.fireAllRules(); for ( int i=0;i < 100; i++) { Person person = new Person(); person.setName( "Test" ); ksession.insert(person); ksession.fireAllRules(); } } private static void initRules() { KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); // this will parse and compile in one step kbuilder.add(ResourceFactory.newClassPathResource( "main.drl" , Main.class), ResourceType.DRL); // Check the builder for errors if (kbuilder.hasErrors()) { System .out.println(kbuilder.getErrors().toString()); throw new RuntimeException( "Unable to compile \" main.drl\ "." ); } // get the compiled packages (which are serializable) Collection<KnowledgePackage> pkgs = kbuilder .getKnowledgePackages(); // add the packages to a knowledgebase (deploy the knowledge packages). KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages(pkgs); ksession = kbase.newStatefulKnowledgeSession(); ksession.addEventListener( new DebugWorkingMemoryEventListener()); } } The Person is a simple POJO Person.java public class Person { private String name; public String getName() { return name; } public void setName( String name) { this .name = name; } } The rule file that does the matching is like this: main.drl package drools; dialect "mvel" declare Stuff regexp : String end rule "Test Regex" salience 100 when then Stuff s = new Stuff( "Test" ) System .out.println( "Insert reg ex variable" ); insert (s); end rule "Test Equality" salience 10 when Stuff( $regexp : regexp ) Person( name matches $regexp ) //Person( name matches "Test" ) then System .out.println( "Found name" ); end rule "Dump person" when $p : Person( ) then retract ( $p ) end

    Description

      When an event is inserted and fired multiple times where the matches operator is used using a variable (instead of a constant string), a separate thread can be spawn and cause a null pointer exception.

      Exception in thread "Thread-0" java.lang.NullPointerException
      	at org.drools.rule.constraint.ConditionAnalyzer.analyzeSingleCondition(ConditionAnalyzer.java:113)
      	at org.drools.rule.constraint.ConditionAnalyzer.analyzeCondition(ConditionAnalyzer.java:99)
      	at org.drools.rule.constraint.ConditionAnalyzer.analyzeCondition(ConditionAnalyzer.java:70)
      	at org.drools.rule.constraint.MvelConditionEvaluator.getAnalyzedCondition(MvelConditionEvaluator.java:83)
      	at org.drools.rule.constraint.MvelConstraint.executeJitting(MvelConstraint.java:269)
      	at org.drools.rule.constraint.MvelConstraint.access$200(MvelConstraint.java:50)
      	at org.drools.rule.constraint.MvelConstraint$ConditionJitter.run(MvelConstraint.java:249)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      	at java.lang.Thread.run(Unknown Source)
      

      This problem disappear when the regexp is a constant string instead of a variable. No new thread is spawned when using the constant string.

      The thread spawning was observed using a separate profiler tool.

      The exception usually happens in the middle of the console output. A search on null pointer exception will get you there.

      Attachments

        Activity

          People

            mfusco@redhat.com Mario Fusco
            azerith Andreas Ali (Inactive)
            Archiver:
            rhn-support-ceverson Clark Everson

            Dates

              Created:
              Updated:
              Resolved:
              Archived:

              PagerDuty