I have some doubts regarding the order in which the rules are activated if they are given the attribute auto-focus.
For example, if I have the following rule-file:
rule "Rule1" salience 2
agenda-group "group1"
auto-focus
when
...
then
...
end
rule "Rule2" salience 1
agenda-group "group2"
auto-focus
when
...
then
...
end
and I pass a fact which activates both the rules, I observe that the agenda groups are stacked in the order:
group2
group1
which means that Rule2 is executed first.
Now if I reverse the order of the rules:
rule "Rule2" salience 1
agenda-group "group2"
auto-focus
when
...
then
...
end
rule "Rule1" salience 2
agenda-group "group1"
auto-focus
when
...
then
...
end
I observe that Rule1 is fired first now.
Does this mean that salience does not affect the order of activations in case of auto-focus, but instead it depends on the order in which the rules are written in the rules file ?
I went through this discussion regarding this topic but did not find satisfactory answers.
If the behavior I described is correct, is it documented anywhere ?
I am using Drools 6.2.0.
Many of the rule attributes are ad-hoc extensions that have been invented to allow rule authors to reduce the logic of their rules. You should be very careful whenever a SW feature announces "auto(matic)".
If an activation (which is not the same as executing) sets an agenda-group, then salience will only decide within that group. Salience, on the other hand, does not govern the evaluation order.
Remove the auto-focus and the agenda-group if you need to handle the decision between two or more agenda-groups by a rule. Call e.g.
drools.setFocus( "group1" );
on the right hand side of the rule doing the selection.
Related
I'm new to drools (I can consider Kogito as well) we have a requirements where the rules with orders are stored in a decision table and it should be executed based on the order given by the users the rules order could change at anytime. Please keep in mind that the response(output) from any rules is the input for the next one. is there anyway to achieve this?
example:
Rules
rank
rule 1
1
rule 2
2
order might change to:
Rules
rank
rule 1
2
rule 2
1
I've few drools rules that I want to use in different rule flows. Since, Drools rule supports only one ruleflow-group name at a time and rule flow business rule task also can be mapped with single ruleflow-group, I'm not able to use same rule in different rule flows. Is there any other way that I can use to filter the rules? like using tags or and metadata?
You could create your own rule groups. You create a class OwnRuleGroup with String group in it as a field. Then when you fire rules you create an instance of your own rule grup:
OwnRuleGroup myGroup = new OwnRuleGroup();
myGroup.group = "foo";
and insert it into session with other facts. In every rule you could specify which of the groups you want to fire.
rule "This will fire for groups foo,bar"
when
OwnRuleGroup(group in ["foo", "bar"])
rule "one"
activation-group "Harris"
salience 10
when
$p : Person(age < 10);
then
$p.setDiscount(0.1);
end
rule "two"
activation-group "Harris"
salience 10
when
$p : Person(age > 10);
then
$p.setDiscount(0.2);
end
When I insert some Persons to working memory through KSession.insert(Object), only the first Person is evaluated, the other persons just ignored. My understanding about Drools activation-group is that if I have X number of rules that belong to the same activation-group with various salience values that each
Person will be processed by the rules and the one with the highest
salience will be fired and the rest will be ignored. Once that's
complete the next Person will come through and repeat the process. What
I'm experiencing is that the first Person to trigger any rule in that
activation-group will disable the entire activation group and no further
Persons will be processed.
Any suggestion?
"Only one rule within an activation group will fire, i.e., the first one to fire cancels any existing activations of other rules within the same group." This is pretty explicit.
Don't use an activation group if you want to do the same thing for many Person facts.
(a) Insert just one, fire all rules - repeat.
(b) Insert many persons, fire all rules but retract a Person fact in each consequence.
Salience is almost always bad. Use logic (constraints) for fine-grained control of the rule firing order.
activation-group will not work in your case. Insert and fireAlleules one by one shockingly that will work because it will fire up the rules considering the new updates in KnowledgeBase.(Not Recommended).
But i would suggest you to write up the unique rules to avoid activation-group. You can also try extending rules for more constructive.
PROBLEM :
I have three rule tables in Decision Table (Spreadsheet) the rules of first two rule table defines which rule is to be fired from the third rule table. In First rule table according to some conditions, I have updated the fact and this fact is used to fire a rule from second rule table. And in ACTION column of second rule table I have updated the fact and I want to fire rules in 3rd Rule table based on this updated fact, but because of updated fact the rule from the first table fires again and then second and the loop goes on.
I can't find the way to add RuleFlow-Group in rule table whenever I add RuleFlow-Group the rules stops firing for any fact.
WHAT I TRIED :
I have added No-Loop to true so that no rules are firing of the same rule table for the updated fact.
I tried adding LOCK-ON-ACTIVE attribute, rules from the Rule Table 1 are working fine but no other rules are getting firing.
I think after firing the rule from Rule Table 1 it locks all the rule of the Rule Package instead, I am adding "lock-on-active" in Rule Table, not in Rule Set.
Spread Sheet illustrating problem statement.
This is a very abstract set of rules, and I don't feel that it's worth discussing in depth. Updating a fact means it is re-evaluated wherever it occurs, which is in all rules. To avoid re-evaluation, use constraints that keep the rule from firing if the result of the RHS is already set in the fact.
rule "table_1_1"
when
$input: Input(a==1, b!=1)
then
modify( $input ){ setB( 1 ); }
end
rule "table_2_1"
when
$input: Input(b==1, c!=1)
then
modify( $input ){ setC( 1 ); }
end
The third table isn't using modify so it doesn't cause a loop.
I read the rule file and add them into my knowledgeBase then I want to fire a particular rule in that knowledgeBase. Is this task possible in current drools version?
If you have a rule base where rules should be made active dynamically according to some criterion you have several choices.
Agenda filter. You say you don't want this, but why?
Put the alternative rules into agenda groups. Select the agenda group "group_3" prior to inserting the fact by a call to
kieSession.getAgenda().getAgendaGroup( "group_3" ).setFocus();
Write your rules to include a "selection" fact, e.g.
rule rule_3
when
Select( rule == "rule_3" )
Person( ... )
then ... end
The Select fact can be inserted along with the data fact but must be retracted after firing the rule.