In previous chapter we implemented a drools project to understand backward chaining. In this tutorial we will try to understand the attributes update statement and no-loop.
- Using update makes the rules engine aware that a fact has been modified. This may cause other depending rules to get fired again.In some scenarios as shown below it cause indefinite looping.
- Indefinite looping can be avoided using the no-loop attribute as shown in below example.
1) Create Example
For our example here we will use the example of mobile shop we used before. Create the project structure follows-
Download counts: 3607
- After downloading, unzip the project.
- Go to Eclipse IDE -> File -> Import -> Maven -> Existing Maven project -> Select the project.
2) Understanding Update attribute
We will be modifying the files as follows. In the product class we add an additional field buyer.
package com.hi.techpoints.model;
public class Product {
private String model;
private int discount;
private String buyer;
public Product(String model, int discount, String buyer) {
super();
this.model = model;
this.discount = discount;
this.buyer = buyer;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getDiscount() {
return discount;
}
public void setDiscount(int discount) {
this.discount = discount;
}
public String getBuyer() {
return buyer;
}
public void setBuyer(String buyer) {
this.buyer = buyer;
}
}
In drl file we add an additional rule “if customer/buyer is gold membership”. The rules ‘Offer for Iphone’ and ‘Offer for Pixel’ are executed sequentially . This will cause the other two discount rules to be applied again so the discount will be doubled. However we have not used a no-loop attribute here so the rule “if customer is gold” will get applied indefinitely.
import com.hi.techpoints.model.Product
rule "Offer for Iphone"
when
productObject: Product(model == "Iphone")
then
productObject.setDiscount(5 + productObject.getDiscount());
System.out.println("Offer for Iphone");
end
rule "Offer for Pixel"
when
productObject: Product(model == "Pixel")
then
productObject.setDiscount(10 + productObject.getDiscount());
System.out.println("Offer for pixel");
end
rule "if buyer is gold membership"
when
productObject: Product(buyer == "Gold")
then
System.out.println("This is gold membership customer double the discount");
update(productObject)
end
package com.hi.techpoints;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import com.hi.techpoints.model.Product;
public class RunDrools {
public static final void main(String[] args) {
try {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rule");
Product product = new Product("Pixel", 0, "Gold");
kSession.insert(product);
kSession.fireAllRules();
System.out.println("The discount for the mobile product "
+ product.getModel() + " is " + product.getDiscount());
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Get the output as-
3) Understanding no loop attribute
In drl file we add an attribute no-loop for rule “if customer is gold”. This avoids our rule getting executed indefinitely and gets executed only once.
import com.hi.techpoints.model.Product
rule "Offer for Iphone"
when
productObject: Product(model == "Iphone")
then
productObject.setDiscount(5 + productObject.getDiscount());
System.out.println("Offer for Iphone");
end
rule "Offer for Pixel"
when
productObject: Product(model == "Pixel")
then
productObject.setDiscount(10 + productObject.getDiscount());
System.out.println("Offer for pixel");
end
rule "if buyer is gold membership"
no-loop true
when
productObject: Product(buyer == "Gold")
then
System.out.println("This is gold membership customer double the discount");
update(productObject)
end
package com.hi.techpoints;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import com.hi.techpoints.model.Product;
public class RunDrools {
public static final void main(String[] args) {
try {
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rule");
Product product = new Product("Pixel", 0, "Gold");
kSession.insert(product);
kSession.fireAllRules();
System.out.println("The discount for the mobile product "
+ product.getModel() + " is " + product.getDiscount());
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Get the output as-
If the buyer is not a gold customer only the rules “Offer for Iphone” or “Offer for Pixel” will get applied once. If the buyer is a gold customer the rules “Offer for Iphone” or “Offer for Pixel” will get applied twice, once before the update call and once after the update call. So the discount gets applied twice if the customer is a gold customer.