0

Please have a look at the two code settings below.

Setting 1:

public class DroolsAnotherTest {
    private static KieSession kSession;
    private static Building building;
    private static FactHandle buildingFact;
    public static final void main(String[] args) {
        try {
            // load up the knowledge base
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            kSession = kContainer.newKieSession("ksession-rules");
            building = new Building();
            building.setRooms(2);
            buildingFact = kSession.insert(building);
            kSession.fireAllRules();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public static void fireAgain(){
        System.out.println("inside fireAgain method");
        kSession.fireAllRules(); // firing the rules second time
    }
public static class Building {

        public int rooms;
        public int getRooms() {
            return this.rooms;
        }
        public void setRooms(int rooms) {
            this.rooms = rooms;
        }
    }
}

And the .drl file

package com.sample

import com.sample.DroolsAnotherTest.Building;
import com.sample.DroolsAnotherTest;

rule "Building"
    when
        Building( rooms <3 )
    then
        System.out.println( "Building rule fired" );
        DroolsAnotherTest.firingAgain();
end

Upon running, the output is : Building rule fired

inside fireAgain method


Setting 2: Here I just changed the fireAgain() method to:

public static void fireAgain(){
                System.out.println("inside fireAgain method");
        kSession.delete(buildingFact);
        building.setRooms(4);
        kSession.insert(building);
        kSession.fireAllRules(); // firing the rule second time
}

everything else is same. Upon running, the output is same again : Building rule fired

inside fireAgain method


As per my understanding,

in Setting 1, the rule did not get fired second time because the fact has not changed in the working memory.

in Setting 2, the rule did not get fired second time because now the fact has updated and it does not match with the rule condition.

My question is, does Drools generate any event for the setting 2 ( the rule fired once but now is not fired again because fact has updated ?) In that way I can distinguish between : a rule did not get fired because the fact are unchanged and it did not get fired because now the fact does not match with rule condition ?

1 Answers1

0

There is no way you can determine why a rule isn't put on the agenda.

You know when you update a fact, so if this interesting for some reason, register it in the fact or elsewhere.

And DO NOT, repeat: DO NOT, call fireAllRules while another such call on the same session is still executing. There may be all kind of unexpected effects.

laune
  • 31,114
  • 3
  • 29
  • 42
  • Thanks @laune. It is kind of sad to find that Drools does not offer anything like that. There is a method matchCancelled(MatchCancelledEvent event) in AgendaEventListener, but I have no idea when this event is generated. Can you shed some light on this ? – InconsistentHashing Aug 18 '17 at 19:44
  • Hi @laune, can you please help me understand in details about the last part of your answer ? 'There may be all kind of unexpected effects.' ! Any example or article discussing this problem ? – InconsistentHashing Aug 19 '17 at 20:03
  • You've managed to make a recursive call on a method that isn't meant to be called recursively. Data on the stack should be safe, but there's no guarantee that all objects in and around the session (e.g., the agenda) are not affected by the abuse. If there are more rules to be fired they'll be fired anyway, without calling fireAllRules over and over again. – laune Aug 22 '17 at 06:45
  • Got it. Actually my use case is to first check the rule, then to do some update ( which is done by some other module), and then continue to check whether I can apply further rule and update again, until a situation arrive where no more rule can be applied. Is there any better way to achieve this than what I am doing? Thanks in advance. – InconsistentHashing Aug 23 '17 at 05:51
  • Well... The idea is to let the engine run in its stateful session until rules don't fire any more. Updates can be done without restarting the running engine. – laune Aug 23 '17 at 07:41