Search code examples
scalarestakkadroolsactor

Drools rules not firing from Akka actor system


We've built a Drools module in Scala which runs just fine when called separately, however now we're integrating it into an Akka actor system we've built to be able to fire rules via REST calls.

For some reason no rules are firing whatsoever, even blank rules such as:

rule "sample 1"
    salience 1000
    auto-focus true
    when

    then
        System.out.println("Well, that finally worked!");
    end

The KieContainer, Session etc. seem to be fine and the objects (facts) are being inserted correctly (verified by checking the Fact Count). (The KieServices and KieContainer are being initialised at boot level, i.e. before the actors are created, and used at a later stage.) The strange thing is that when running kieSession.fireallrules() the total number of rules fired is always 0 and the facts aren't updated.

Using Akka, we're sending an object (of type MyObject) in JSON format via REST. An actor is created per REST request and calls the Drools module as below:

  • A new actor is created to call the Drools Engine.
  • A new KieSession is created using the KieServices set at Boot level. [For those who've seen my previous posts, yes the following is Scala code]

val kieSession = DroolsMgt.getKieSession(List("myFile.drl"), Boot.kieServices) where getKieSession is calling the following:

    val kfs = kieServices.newKieFileSystem()
    for (filename <- drlFiles) {
      val fis = new FileInputStream(filename)
      kfs.write(filename, kieServices.getResources.newInputStreamResource(fis))
    }

    val kieBuilder = kieServices.newKieBuilder(kfs).buildAll()

    val kieContainer = kieServices.newKieContainer(kieServices.getRepository.getDefaultReleaseId)

    kieContainer.newKieSession()
  • The object received via REST (which is extracted from the JSON format) is then loaded into Drools Memory via ksession.insert(testObject) and the object's FactHandle is saved

  • The rules are then fired and the updated object is returned using its FactHandle as follows: ksession.fireAllRules() val getObject = ksession.getObject(myObjectFH) ksession.dispose() getObject.asInstanceOf[MyObject]

As before, this works when running the Drools Module on its own but not when using the actor system as above. I've even tried firing empty rules and printing text out onto the screen for debugging purposes but literally no rules are being fired. I am sure I'm calling the right DRL file and the right KieSession but can't figure out what's going wrong here. (Is there any way to check the number of rules in a KieSession?)

Any ideas?

EDIT: After looking into laune's suggestion I found that there weren't any KiePackages being loaded into the KieBase. I've narrowed this down to the files not being loaded as KieResources at kfs.write("src/main/resources/testFile.drl", kieServices.getResources().newInputStreamResource(fis))

Any idea what might be causing this?

For reference, I'm loading DRL files into the KieContainer and creating the KieSession (successfully) as follows:

    val kieServices = KieServices.Factory.get()

    val kfs = kieServices.newKieFileSystem()
    val fis = new FileInputStream("src/main/resources/testFile.drl")

    kfs.write("src/main/resources/testFile.drl", kieServices.getResources().newInputStreamResource(fis)) 

    val kieBuilder = kieServices.newKieBuilder(kfs).buildAll()

    val results = kieBuilder.getResults()
    if (results.hasMessages(Message.Level.ERROR)) {
        throw new RuntimeException(results.getMessages().toString())
    }

    val kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId())


    kieContainer.newKieSession()

Solution

  • The following code will not fix your problem but it should help you diagnose whether you really run the rules and the session you think you do. I'm using Java notation.

    KieSession kieSession = ...
    KieBase kieBase = kieSession.getKieBase();
    Collection<KiePackage> kiePackages = kieBase.getKiePackages();
    for( KiePackage kiePackage: kiePackages ){
        for( Rule rule: kiePackage.getRules() ){ 
            System.out.println( rule.getName() );
        }
    }