2 Replies Latest reply on Dec 30, 2015 11:36 AM by reynoldsm88

    Error Executing Rule with Domain Model Classes

    reynoldsm88

      Hello,

       

      I am testing some updates in upstream Drools to see if it fixes one of the issues I am having, however I do not believe the rules are executing as I expect. The changes in question are detailed here: https://github.com/droolsjbpm/drools/pull/589

       

      I am trying to execute my Drools code by handing off a "request" object with Domain Model facts into a BRMS service. However, any rules that use the domain model objects do not seem to be able to match and create an activation with the rule. Also, as demonstrated in the rule included, it seems that this only applies to the Domain model classes from my project, regular java.lang classes seem to work fine. Here is the code that actually executes the rules:

       

      public RulesResponse execute( RulesRequest request ) {
             
      List<Command> commands = new ArrayList<Command>();

             
      KieSession kSession = kieSessionService.getNamedKieSession( request.getKieSession() );

              commands
      .add( CommandFactory.newEnableAuditLog( "/home/developer", "audit" ) );

             
      if ( request.getProcessName() != null && !"".equals( request.getProcessName() ) ) {
                  commands
      .add( CommandFactory.newStartProcess( request.getProcessName() ) );
             
      }

              commands
      .add( CommandFactory.newInsertElements( request.getFacts() ) );
              commands
      .add( CommandFactory.newFireAllRules() );

              kSession
      .execute( CommandFactory.newBatchExecution( commands ) );

             
      RulesResponse response = request.getResponse();
              response
      .processResults( kSession );

              kSession
      .dispose();

             
      return response;
         
      }

       

       

      Here are my rules, I have another jar which exports MyModelObj and MyOtherModelObj. The curious thing is that the first rule does not fire, despite the fact that the output of the second rule (which does fire) confirms that the classes line up. Nevertheless, no activations are created for the first rule ever.

      //created on: Dec 3, 2015
      package com.redhat.rules

      //list any import classes here.
      import com.redhat.drools.camel.model.MyModelObj;
      import com.redhat.drools.camel.model.MyOtherModelObj;

      //declare any global variables here


      rule
      "Your First Rule"
         
      when
             
      MyModelObj()
         
      then
             
      System.err.println( "here" );

      end

      rule
      "Test"
         
      when
              $o
      : Object()
         
      then
             
      System.err.println( $o.getClass() );
      end

       

       

      The output of executing this produces the output in the console "class com.redhat.drools.camel.model.

      MyModelObj", meaning that the first rule fired and printed out the class of the inserted fact. Also for reference, here is the Audit log detailing what happened during the engine execution:

       

       

      Enter code here...<object-stream>
      <org.drools.core.audit.WorkingMemoryLog>
       
      <version>6.1</version>
        <events>
          <org.drools.core.audit.event.ObjectLogEvent>
            <type>1</
      type>
           
      <factId>1</factId>
            <objectToString>MyModelObj [value=0987654]</
      objectToString>
         
      </org.drools.core.audit.event.ObjectLogEvent>
          <org.drools.core.audit.event.ActivationLogEvent>
            <type>4</
      type>
           
      <activationId>Test [1]</activationId>
           
      <rule>Test</rule>
            <declarations>$o=MyModelObj [value=0987654]</
      declarations>
           
      <factHandleIds>1</factHandleIds>
          </
      org.drools.core.audit.event.ActivationLogEvent>
         
      <org.drools.core.audit.event.ActivationLogEvent>
           
      <type>6</type>
            <activationId>Test [1]</
      activationId>
           
      <rule>Test</rule>
            <declarations>$o=MyModelObj [value=0987654]</
      declarations>
           
      <factHandleIds>1</factHandleIds>
          </
      org.drools.core.audit.event.ActivationLogEvent>
         
      <org.drools.core.audit.event.ActivationLogEvent>
           
      <type>7</type>
            <activationId>Test [1]</
      activationId>
           
      <rule>Test</rule>
            <declarations>$o=MyModelObj [value=0987654]</
      declarations>
           
      <factHandleIds>1</factHandleIds>
          </
      org.drools.core.audit.event.ActivationLogEvent>
       
      </events>
        <engine>PHREAK</
      engine>
      </org.drools.core.audit.WorkingMemoryLog>
      </
      object-stream>

       


      Can anyone lend some insight into why I do not see the first rule fire, despite the fact that everything I've done seems to indicate that it should fire? For those interested the full source code of this use case is provided here: https://github.com/reynoldsm88/brms-fuse-integration

       

      Thanks,
      Michael
        • 1. Re: Error Executing Rule with Domain Model Classes
          reynoldsm88

          I did some debugging and I am seeing one major difference between the Object rule and the model object rule. When inserting I traced the behavior into the ObjectType node resolution and found something interesting. The model object fails a check in ObjectTypeNode.isAssignableFrom (ObjectTypeNode line 248) which calls into ClassObjectType to perform the following check:

           

          public boolean isAssignableFrom(ObjectType objectType) {

                  return objectType instanceof ClassObjectType && this.cls.isAssignableFrom( ( (ClassObjectType) objectType ).getClassType() );

          }

           

          In this case, the ObjectType in the argument has cls value com.redhat.drools.camel.MyModelObj, however it fails the check in bold above. Could this have something to do with the fact that this is being executed in an OSGI environment and be an issue with classloading/resolution?

          • 2. Re: Error Executing Rule with Domain Model Classes
            reynoldsm88

            I found out the issue...

             

            Since the rules were being built via a KJar that is loaded from a KieScanner, the classes as resolved in the rules were not compatible with the classes loaded from the model jar classloader (this is OSGI, so I am assuming something weird occurred with the classloader wiring).

             

            The fix is very easy, and just requires that you tell KieServices which classloader to use when building the KieContainer:

            KieServices kieServices = KieServices.Factory.get();

            kieContainer = kieServices.newKieContainer( kieServices.newReleaseId( groupId, artifactId, version ), this.getClass().getClassLoader() );

            kieScanner = kieServices.newKieScanner( kieContainer );

            kieScanner.scanNow();

            kieScanner.start( 30000 );