I'm having a strange issue with drools :
I have the following rules :
rule "is my dog a baby?"
ruleflow-group "dog"
salience 10
when
dog : Dog(age <1 )
then
dog.setIsBaby(true);
end
rule "baby dog"
ruleflow-group "dog"
salience 9
when
myData : MyData( myDog.isBaby() == false)
then
System.out.println(myData.getMyDog().getIsBaby());
end
I insert in my session myData and myData.getMyDog()
, where myData.getMyDog.isBaby==false
The first rule is fired and my dog is set to be a baby. Then the second one is fired, and even it prints true .(even if the condition was to be false)
And when I test after firing all rules , myDog 开发者_JS百科in myData is set to be a baby .
What am I doing wrong here ? Why does the second rule is fired ? is the problem in the session (stateful in my case) ?
I think that I need to say that I modify myData:myDog somewhere ,but I am not sure where .
Hope my question is clear, if not tell me.
When you modify working memory facts, you need to tell Drools that the data has changed so it can re-evaluate all relevant rules.
Drools evaluates facts before firing any matched rules. If you have a dog with age = 0 and baby = false, both your rules will be activated. When your is my dog a baby?
rule is fired, it doesn't change the fact that when Drools evaluated the baby dog
rule, the myDog.isBaby() == false
condition was true.
To inform Drools that you have modified some fact, use the update()
knowledge helper method. Keep in mind that Drools associates fact handles to a specific object. If a rule references MyData
, and you want that rule to be re-evaluated when the MyData.myDog
object has changed, you'll need to use update()
on the MyData
object; just doing update()
on your Dog
object, will not cause the baby dog
rule to be re-evaluated.
Try changing your is my dog a baby?
rule to the following:
rule "is my dog a baby?"
ruleflow-group "dog"
salience 10
when
dog : Dog(age < 1, baby == false)
myData : MyData(myDog == dog)
then
dog.setIsBaby(true);
update(dog);
update(myData);
end
You need to do
then
dog.setIsBaby(true);
update( dog )
on your first rule and rewrite the when of your second rule like
when
dog : Dog( isBaby == false)
myData : MyData( myDog == dog)
The rule has to be written in this way, so drools can automatically detect which rules it has to run again after a fact changes.
Every time you change a fact in the rules engine, you need to tell the working memory that you've changed it with update.
I haven't used drools since version 4, but I assume that this still applies.
Yes you should update both the dog and the map. Cheers
You can update the dog in working memory by using modify
or update
knowledge helper methods. If you can any of the above function Drools will re-evaluate the rules again and you will end up with an infinite loop. so you also need to you no-loop attribute in your rule or modify you condition to
dog : Dog(age <1, isBaby == false )
so that the next time it will not evaluate the same rule again and update the isBaby to true again and again.
精彩评论