Drools

Drools – update statement and no-loop attributes

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.

  1. 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.
  2. 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 Drools Attributes
Download counts: 220
  1. After downloading, unzip the project.
  2. 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.

About the Author: Elavarasan PK

Technical Specialist, Intersoft Data Labs