Almas Kamitov
Almas Kamitov

Reputation: 103

How to control rule evaluation (or rule execution) stages in Drools?

I know that "salience" in Drools provides control under rule execution sequence. But above is an example of the problem when "saliences" cannot help anymore that I've faced with.

Here I have three rules being executed one after another:

rule "Rule 1"
salience 30
when

then
    Resource resource1 = new Resource();
    resource1.setName("Resource 1");
    resource1.setAmount("5");
    insert(resource1);
    System.out.println("First");
end

rule "Rule 2"
salience 20
//no-loop (interesting, it doesn't lead to a loop)
when
    $resource1: Resource(name == "Resource 1")
then
    modify($resource1) {setAmount("20")};
    System.out.println("Second");
end

rule "Rule 3"
salience 10
when
    $resource1: Resource(name == "Resource 1", 
    Double.parseDouble(amount) > 10)
then
    System.out.println("Rule is fired");
end

I expected the third rule is fired and there's a "Rule is fired" line in the console, but it is not executed.
As I understand the issue is with rules evaluation stage when all three rules are evaluated at once before execution and only then are executed according to their "salience" turn.
And on the moment of evaluation $resource1.amount is 5, that is why third rule wasn't fired. If you put a number more than 10 in the first rule the 3d rule will fire. And if you don't set amount at all - it leads to exception.
How can I solve this issue so that the 3d rule fires?

Upvotes: 0

Views: 2158

Answers (4)

dormi330
dormi330

Reputation: 1353

I tested the code, and rule3 is fired

drools.version 7.32.0.Final

enter image description here

Upvotes: 0

Almas Kamitov
Almas Kamitov

Reputation: 103

So it was a bug and now it is fixed in one of last updates. Here is the issue: https://issues.jboss.org/browse/DROOLS-3972

Upvotes: 0

Esteban Aliverti
Esteban Aliverti

Reputation: 6322

My guess is that Drools doesn't understand that the expression Double.parseDouble(amount) > 10 must be re-evaluated when you change the amount of your fact. The problem is related with the way you are writing your expression.

You can take a look at my answer in this other question. Take a look at the "Another solution" part.

What I would suggest you to do is to modify your model and add a getAmountAsDouble() method to you class so the conversion happens inside it. You will also need to annotate the setAmount() method to let Drools know that it modifies the value returned by getAmountAsDouble():

public class Resource {

  private String amount;

  @Modifies( { "amountAsDouble" } )
  private void setAmount(String amount){
    this.amount = amount;
  }

  private String getAmount(){
    return this.amount;
  }

  private String getAmountAsDouble(){
    return Double.parseDouble(this.amount);
  }

}

Now your rule can be rewritten as:

rule "Rule 3"
salience 10
when
    $resource1: Resource(name == "Resource 1", 
    amountAsDouble > 10)
then
    System.out.println("Rule is fired");
end

Hope it helps,

Upvotes: 2

salaboy
salaboy

Reputation: 4133

Look in the docs for Agenda/activation Groups, you can control the execution of rule groups using that concept

Upvotes: 0

Related Questions