Using drools 6.4-FINAL
We have two rules;
rule "Rule1"
when
// conditions
$aclass: AClass(type == AType.DOG);
$bclass: BClass(type == BType.SHIP);
$cclass: CClass();
$xclass: XClass();
then
//actions
System.out.println("Actioning Rule1");
end
rule "Rule2"
when
// conditions
$aclass: AClass(type == AType.DOG);
$bclass: BClass(type == BType.SHIP);
$cclass: CClass();
$yclass: YClass();
then
//actions
System.out.println("Actioning Rule2");
end
Notice that the first 3 conditions of both rules are the same (matching over the classtype and an inner type in some cases of classes AClass, BClass and CClass. The rules differ on with XClass or YClass is present in the facts.
We are finding the following behaviour;
- If classes A,B,C and Y are provided Rule2 fires.
- If classes A,B,C and X are provided no rules fire, even though Rule1 should have.
- Deleteing Rule2 allows Rule1 to fire when A,B,C and X are provided.
- Swapping the rules around in their order in the file reverses the above behaviour (X = Rule1 fires, Y = no fire even though Rule2 should do).
- Again in this reverse order, deleteing the second rule allows the first to fire.
Can anyone explain what is going on here. While I suspect the ordering is a red herring, it does look like the first rule to attempt to match somehow consumes the facts, or there is some conflict in assigning facts to variables.
UPDATE
After further investigation I oversimplified the code above. Rather than enum comparison in BClass there is actually a getter such that;
public Class<?> getConfigClass() {
return BConfig.class;
}
And the rules BClass line actually reads;
$bclass: BClass(configClass == BConfig.class);
We have refined the issue down to the BClass line. The class comparison somehow consumes or conflicts. Adding further rules (say Rule3, Rule4) of the same format only exacerbates the issue. Further reducing the rules to remove their only differentiating Class (X or Y);
rule "Rule1"
when
// conditions
$aclass: AClass(type == AType.DOG);
$bclass: BClass(configClass == BConfig.class);
$cclass: CClass();
then
//actions
System.out.println("Actioning Rule1");
end
rule "Rule2"
when
// conditions
$aclass: AClass(type == AType.DOG);
$bclass: BClass(configClass == BConfig.class);
$cclass: CClass();
then
//actions
System.out.println("Actioning Rule2");
end
rule "Rule3"
when
// conditions
$aclass: AClass(type == AType.DOG);
$bclass: BClass(configClass == BConfig.class);
$cclass: CClass();
then
//actions
System.out.println("Actioning Rule3");
end
Passing in facts that satisfy those 3 conditions (ie AClass with getType == AType.DOG, BClass with getConfigClass == BConfig.class and a CClass) always runs the last rule, no matter how many rules there are.
Removing the BClass class comparison condition and re-running the test fires all rules as expected.
It seems very strange behaviour that given that one rule fires, the class comparison is valid, but only for one rule?