Search code examples
drools

Drools 6 loading and executing rule from String


I am trying to load a rule from a String in Drools 6 like this:

// the rule
def drl = '''
dialect "mvel"

rule "Person is over 18"
    when
        $person : Person(age > 18)
    then
        System.out.println("Person is "+$person.name);
end
'''
// setup for rule
KieServices kieServices = KieServices.Factory.get()
KieFileSystem kfs = kieServices.newKieFileSystem()
kfs.write( "src/main/resources/simple.drl",
    kieServices.getResources().newReaderResource( new StringReader(drl) ) )
KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll()

// check there have been no errors for rule setup
Results results = kieBuilder.getResults();
if( results.hasMessages( Message.Level.ERROR ) ){
    println( results.getMessages() )
    throw new IllegalStateException( "### errors ###" )
}
KieContainer kieContainer =
    kieServices.newKieContainer( kieBuilder.getKieModule().getReleaseId() )
KieSession kieSession = kieContainer.newKieSession()

// insert facts and fire rules
kieSession.insert(new Person("Jon Doe", 21))
kieSession.insert(new Person("Jon Darcy", 1))
kieSession.fireAllRules()

kieSession.dispose()

@Immutable
class Person {
    String name
    int age
}

What I wanted to happen is getting the person name printed out. By attaching eventlistener and logger I can see that the facts are added and asserted. By having an error in the drl I can be sure the rule is seen and compiled. But the rule never fires.

I am pretty sure there is jsut a stupid little mistake somewhere in the code. Can somebody help me?


Solution

  • Getting a KieBase from the KieContainer and creating the KieSession from that is what works for me:

    KieContainer kieContainer =
       kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId() );
    KieBase kieBase = kieContainer.getKieBase();
    KieSession kieSession = kieBase.newKieSession();
    

    But your code is working, too - at least after doing it all in Java, and making sure that Person and the DRL file are in the same package.

    String drl = "package drlstring;\n" +
        "dialect 'mvel'\n" +
        "rule Person_is_over_18\n" +
        "when\n" +
        "$person : Person(age > 18)\n" +
        "then\n" +
        "System.out.println(\"Person is \"+$person.getName());\n" +
        "end";
    // setup for rule
    KieServices kieServices = KieServices.Factory.get();
    KieFileSystem kfs = kieServices.newKieFileSystem();
    kfs.write( "src/main/resources/simple.drl",
           kieServices.getResources().newReaderResource( new StringReader(drl) ) );
    KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
    
    // check there have been no errors for rule setup
    Results results = kieBuilder.getResults();
    if( results.hasMessages( Message.Level.ERROR ) ){
        System.out.println( results.getMessages() );
        throw new IllegalStateException( "### errors ###" );
    }
    KieContainer kieContainer =
        kieServices.newKieContainer( kieBuilder.getKieModule().getReleaseId() );
    KieSession kieSession = kieContainer.newKieSession();
    
    // insert facts and fire rules
    kieSession.insert(new Person("Jon Doe", 21));
    kieSession.insert(new Person("Jon Darcy", 1));
    kieSession.fireAllRules();
    kieSession.dispose();
    

    If you want to continue with your Scala setup, narrow the possible causes for the failure to fire down by adding a rule with an empty condition:

    rule hello
    when then 
      System.out.println( "Hello!" );
    end
    

    I think it is the Scala definition of class Person that isn't recognized by the Drools engine.