Reputation: 429
I have a Drools decision table (see below) whereby Rule 2 has a condition that checks whether a nutrient score is between a certain threshold and executes an action based on this condition. There is an initial rule (RULE 1) that performs a check and performs its action, which updates the overall scores that i want Rule2 to use when executing its conditions.
What i expect/need:
Rule 1 to run, if the condition is met then update the overall score on $model (by executing its action) and then rule 2 run and for it's conditions to use the updated score value that was updated by Rule 1's action running.
What's actually happening
Rule 1 runs it's condition, Rule 2 runs its condition, Rule 1's action is run, Rule 2's action is run. Rule 2 is running it's condition before Rule 1's action has run, and therefore uses an outdated score.
I've proven (i think) by changing the priority/salience value that i can change the order in which the rules run their conditions, but it seems that all rule conditions are running before actions. I expected Rule 1's action to run before the next rule.
Have i fundamentally mis-understood the concept? An obvious mistake? Or if anyone has a suggested workaround that would be great.
To clarify this is a stateless ki session.
Thanks in advance, this is driving me mad!
Upvotes: 0
Views: 2458
Reputation: 15179
Drools works by taking all of the rules up front and evaluating whether their conditions are satisfied. Each of these rules is called a "match". When you fire the rules, Drools collects all of the matches, orders them (either naturally or by salience), and then iterates through and executes them one by one.
As the rules are executed, they might change working memory like your example does. Unless you explicitly tell Drools that you're doing so, however, it won't re-evaluate the matches. The match phase has already been completed by the time the rules are executed.
It is possible to tell Drools that you are modifying working memory and that you need it to re-evaluate its rules based on the new data. To do this, you need to use one of the built-in methods:
Method | Explanation |
---|---|
insert |
Put a new fact into working memory. |
delete or retract |
Removes some information (object/s) from working memory. |
update |
Update/replace a fact in working memory. |
modify |
Change fields inside of a fact in working memory. |
Which one you choose depends on what you're trying to do. Note that calling 'update' will call all matches to be re-evaluated ... it's the equivalent of calling "fire rules" a second time with the new data (so the same rule might hit multiple times, which may or may not be intentional). In comparison, insert
will only evaluate subsequent rules to determine if they now match or don't based on the new conditions.
So if your intention is to cause other rules to fire or not by changing the data in working memory, you'll need to use one of these built-in methods to tell Drools that you're making a change that it should re-evaluate its matches for.
I discuss this concept in more detail in this answer specifically about DRL. The same concepts apply to decision tables.
Upvotes: 1