I have a set of rules which behave differently based on number of Objects they are evaluated against
I expect 2 rule to be executed for each Product class object passed.
When I pass single object of Product 2 rules are executed( which is fine)
Product product5= new Product();
product5.setType("gold");
product5.setBuyer("platinum");
product5.setEvent("sale");
product5.setName("product5");
ksession.insert(product5);
When I pass two objects of the Product class the number of rules which get executed is 6 (which I fail to understand).
Product product5= new Product();
Product product3= new Product();
//setting all fields in both objects
ksession.insert(product5);
ksession.insert(product3);
I tried to debug this by adding Console prints, Here are my results
Offer for Gold executed once for each object (expected).
Offer for Gold on Festival executed twice for each object(should be two).
Offer for Diamond was not invoked (expected)
When I pass three objects of the Product class the number of rules which get executed is 12 (which I fail to understand). I tried to debug this by adding Console prints , Here are my results
Offer for Gold executed once for each object (expected).
Offer for Gold on Festival executed thrice for each object(should be two).
Offer for Diamond was not invoked (expected)
Below is my DRL file
rule "Offer for Diamond"
when
$productObject: Product(type == "diamond")
then
$productObject.setDiscount(15);
end
rule "Offer for Gold"
salience 1
when
$productObject: Product(type == "gold")
then
$productObject.setDiscount(25);
end
rule "Offer for Gold on Festival"
when
$productObject: Product(type == "gold") && Product(event == "sale")
then
$productObject.setDiscount($productObject.getDiscount() + 5);
end
Assuming your 2 objects have the same attributes, these are the rules (and facts) that get executed:
As you can see, when you use && between patterns you are creating a cartesian product of all the possible combinations matching them.
In "Offer for Gold on Festival", if you want the rule to be executed once for each object, then you must explicitly tell Drools that the 2 patterns are talking about the same object:
rule "Offer for Gold on Festival"
when
$productObject: Product(type == "gold") &&
Product(this == $productObject, event == "sale")
then
$productObject.setDiscount($productObject.getDiscount() + 5);
end
Now, if your rule is exactly like the one above, it can be simplified by simply doing:
rule "Offer for Gold on Festival"
when
$productObject: Product(type == "gold", event == "sale")
then
$productObject.setDiscount($productObject.getDiscount() + 5);
end
In this case, because you don't have 2 patterns, the rule will be evaluated only once for each Product
.
Hope it helps,