1
votes

I'm having an object as below:

class License{
    private field1;
    private field2;
    private boolean active;
    private String activeMessage;
    private boolean processed = false;

    //Getter and setter methods
}

What I'm trying to do is, based on the values of field1, and field2, I need to set the isActive flag and a corresponding message. However, if either the rule for field1 or field2 is fired, I need to stop the rules processing. That is, I need to execute only 1 successful rule.

I read on a post that doing ksession.fireAllRules(1) will solve this. But the fireAllRules() method is not available in Drools 6. I also tried putting a return; statement at the end of each rule. That didn't help me either.

Finally, I ended up adding an additional field to my object called processed. So whenever I execute any rule, I set the processed flag to true. And if the flag is already set, then I do not execute any rule. This is my rules file:

rule "Check field1"
    when
        $obj : License(getField1() == "abc" && isProcessed() == false)
    then
        System.out.println("isProcessed >>>>>> "+$obj.isProcessed());
        $obj.setActive(true);
        $order.setActiveMessage("...");
        $order.setProcessed(true);
end


rule "Check field2"
    when
        $obj : License(getField2() == "def" && isProcessed() == false)
    then
        System.out.println("isProcessed >>>>>> "+$obj.isProcessed());
        $obj.setActive(true);
        $order.setActiveMessage("...");
        $order.setProcessed(true);
end

However, I see that even now both my rules are being fired. When I try to print the value of isProcessed(), it says true, even though I enter the rule only if isProcessed() is false.

This is how I'm calling the drools engine:

kieService = KieServices.Factory.get();
kContainer = kieService.getKieClasspathContainer();
kSession = kContainer.newStatelessKieSession();
kSession.execute(licenseObj);

It is not just 2 rules, I have a lot of rules, so controlling the rules execution by changing the order of the rules in the drl file is not an option. What is happening here? How can I solve this problem? I am sort of new to Drools, so I might be missing something here.

Thanks.

1

1 Answers

5
votes

Your question contains a number of errors.

It is definitely not true that fireAllRules has disappeared in Drools 6. You might have looked at the javadoc index, to find four (4!) overloaded versions of this method in package org.kie.api.runtime.rule in the interface StatefulRuleSession.

You might easily avoid the problem of firing just one out of two rules by combining the triggering constraint:

rule "Check field1 and field2"
when
    $lic: License(getField1() == "abc" || getField2() == "def" )
    //...
then
    $lic.setXxx(...);
end

You complain that both of your rules fire in spite of setting the processed flag in the fact. Here you are missing a fundamental point (which is covered in the Drools reference manual), i.e., the necessity of notifying the Engine whenever you change fact data. You should have used modify on the right hand side of your rules.

But even that would not have been good enough. Whenever an update is made due to some properties, a constraint should be added to avoid running the update over and over again. You might have written:

rule "Check field1 and field2"
when
    $lic: License(getField1() == "abc" || getField2() == "def",
                  ! active )
    //...
then
    modify( $lic ){ setActive( true ) }
end

You might even write this in two distinct rules, one for each field, and only one of these rules will fire...