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

丶灬走出姿态 提交于 2019-12-13 03:55:33

问题


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?


回答1:


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,




回答2:


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




回答3:


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



来源:https://stackoverflow.com/questions/55559828/how-to-control-rule-evaluation-or-rule-execution-stages-in-drools

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!