问题
We are using drools 7.31 version. We have one big rule which must be reused in other rules. The basic functionality we need is to fire the SUPER rule when both SUPER rule and SUB rule conditions are true. It seems like older version had "extends" keyword using which this was possible. I was looking at this older post which is able to achieve this -
drools rules inheritance
When I tried on my end with 7.31 version, then both SUPER and SUB rules are firing independently. Here is an example of what I am trying to achieve:
rule "super"
@description("Generic super rule")
when
$person : Person()
a : PersonInput() from $person.getInput()
if (a.getPersonId() == 1) break[pvd1]
else if (a.getPersonId() == 2) break[pvd2]
then System.out.println("Default then = " + a.getPersonId());
then[pvd1] System.out.println("Super RULE has person id = " + a.getPersonId());
then[pvd2] System.out.println("Super RULE has person id = " + a.getPersonId());
end
rule "sub" extends "super"
@description("Sub rule")
when
c : PersonInput(HouseholdId == "99999") from $person.getInput()
then
System.out.println("Sub RULE has HouseholdId == 99999 == " + c.getPersonId());
end
The output I am getting is all persons with personId 1/2 of all households first, then then 2nd rule is printing only 99999 household id.
The output that I expect is just to print personId 1/2 of householdId 99999.
Thanks.
回答1:
Drools 7.31 still supports the 'extends' mechanism. The issue here is that when you extend a base rule, the base rule does fire. (This is kind of obvious; if the base rule isn't valid to fire, then the child rule isn't valid to fire. If the base is valid to fire, then it fires. And when the child rule fires, it also fires the parent rule.)
The traditional way to work around this is to use three rules. The "base" rule should have no consequences (that is, no right hand side/then clause) so it simply lists out the common conditions. Then the "super" rule's consequences are in a rule that extends the base rules, doesn't have any additional 'when' conditions, and has the then clause as normal. And the "sub" rule also extends "base", includes its additional conditions, and then its own consequences. If you don't want "super" to fire when "sub" does, you make them mutually exclusive.
Here's an intentionally simplified example:
rule "Base Rule"
when
$person: Person( $input: input != null )
PersonInput( $id: personId in (1, 2) )
then
// intentionally no 'then' clauses
end
rule "Super" extends "Base Rule"
when
// No additional conditions, just use whatever is in Base Rule
then
System.out.println("Person has id: " + $id);
end
rule "Sub" extends "Base Rule"
when
PersonInput( householdId == "99999") from $input
then
System.out.println("Household ID is 99999; id: " + $id);
end
Now if we don't want "Super" to fire when "Sub" does, we just make it mutually exclusive from "Sub":
rule "Super" extends "Base Rule"
when
// This is the condition from Sub, inverted:
PersonInput( householdId != "99999" ) from $input
then
System.out.println("Person has id: " + $id);
end
Basically, when you extend a rule, you're extending both the when and the then clauses. The then
clause (consequences) of the parent rule will fire before the consequences of the child rule. Further, if the child is not valid, but the parent is, you will still fire the parent. So if you have (say) 3 child rules and a parent rule, the parent may be fired up to 4 times: once when it by itself is evaluated, and then 3 more times once per child evaluation. Things get particularly odd when you use stateful sessions and update
/insert
clauses.
The "no consequence" base rule pattern I've shown evolved out of this reality. Following this pattern, it makes no difference how many times "Base Rule" gets fired because there are no side effects (consequences/then clause).
来源:https://stackoverflow.com/questions/61084833/single-inheritance-in-drools