This is a complete tutorial for beginners on developing a Java project using Spring Boot, and Drools Rule Engine (DRL file) from scratch. This tutorial will help you understand basic concepts, configurations, tools required, and coding to execute a simple API application.
The Drools rule engine stores, processes, and evaluates data to execute the business rules or decision models that you define. The basic function of the Drools rule engine is to match incoming data, or facts, to the conditions of rules and determine whether and how to execute the rules.
KIE (Knowledge Is Everything) is an umbrella project introduced to bring all the related technologies together under one roof, and Drools is one among them.
In Drools, a KIE session stores and executes runtime data. The KIE session is created from a KIE base or directly from a KIE container.
1. Open VS Code
- CTRL + SHIFT + p OR Type ‘>’ in the Search bar — Spring Initializr: Create a Maven project
- Specify Spring Boot version — 3.2.2
- Specify project language — Java
- Group Id — com.drools
- Artifact Id — drools-poc
- Specify packaging type — Jar
- Specify Java version — 17
- Dependencies —
- Spring Web
- Lombok
- Specify a folder to generate the boilerplate project with dependencies injected
2. Update pom.xml with Drools dependencies
<properties>
<drools.version>8.44.0.Final</drools.version>
</properties>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>${drools.version}</version>
</dependency>
3. Create folders as highlighted
4. Create OrderRequest.java model under the Model folder
package com.drools.droolspoc.Model;
public class OrderRequest {
private String customerNumber;
private Integer age;
private Integer amount;
private CustomerType customerType;
public String getCustomerNumber() {
return this.customerNumber;
}
public void setCustomerNumber(String customerNumber) {
this.customerNumber = customerNumber;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getAmount() {
return this.amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public CustomerType getCustomerType() {
return this.customerType;
}
public void setCustomerType(CustomerType customerType) {
this.customerType = customerType;
}
@Override
public String toString() {
return "{" +
" customerNumber='" + getCustomerNumber() + "'" +
", age='" + getAge() + "'" +
", amount='" + getAmount() + "'" +
", customerType='" + getCustomerType() + "'" +
"}";
}
}
5. Create CustomerType.java model under the Model folder
package com.drools.droolspoc.Model;
public enum CustomerType {
LOYAL, NEW, DISSATISFIED;
public String getValue() {
return this.toString();
}
}
6. Create OrderDiscount.java model under the Model folder
package com.drools.droolspoc.Model;
public class OrderDiscount {
private int discount;
public int getDiscount() {
return this.discount;
}
public void setDiscount(int discount) {
this.discount = discount;
}
@Override
public String toString() {
return "{" +
" discount='" + getDiscount() + "'" +
"}";
}
}
7. Create discount-rules.drl under resources/rules folder
Drools Rule Language (DRL) is a notation established by the Drools open source business automation project for defining and describing business rules. DRL rules are defined in
https://docs.drools.org/8.39.0.Final/drools-docs/docs-website/drools/language-reference/index.html.drl
text files. A DRL file can contain one or more rules that define at a minimum the rule conditions (when
) and actions (then
).
import com.drools.droolspoc.Model.OrderRequest;
import com.drools.droolspoc.Model.CustomerType;
global com.drools.droolspoc.Model.OrderDiscount orderDiscount;
rule "Age based discount"
when
OrderRequest(age < 20 || age > 50)
then
System.out.println("==========Adding 10% discount for Kids/ senior customer=============");
orderDiscount.setDiscount(orderDiscount.getDiscount() + 10);
end
rule "Customer type based discount - Loyal customer"
when
OrderRequest(customerType.getValue == "LOYAL")
then
System.out.println("==========Adding 5% discount for LOYAL customer=============");
orderDiscount.setDiscount(orderDiscount.getDiscount() + 5);
end
rule "Customer type based discount - others"
when
OrderRequest(customerType.getValue != "LOYAL")
then
System.out.println("==========Adding 3% discount for NEW or DISSATISFIED customer=============");
orderDiscount.setDiscount(orderDiscount.getDiscount() + 3);
end
rule "Amount based discount"
when
OrderRequest(amount > 1000)
then
System.out.println("==========Adding 5% discount for amount more than 1000$=============");
orderDiscount.setDiscount(orderDiscount.getDiscount() + 5);
end
8. Create DroolsConfig.java under Config folder
KieContainer and KieModule are a little harder to differentiate, but they’re basically the same thing in practice (container being the runtime implementation, module being the specification.)
The KieServices is a thread-safe singleton acting as a hub giving access to the other Services provided by Kie.
KieBuilder is a builder for the resources contained in a KieModule. KieBuilder. buildAll() builds all the KieBases contained in the KieModule for which this KieBuilder has been created.
package com.drools.droolspoc.Config;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DroolsConfig {
private static final String drl_file_path = "rules/discount-rules.drl";
private static final KieServices kieServices = KieServices.Factory.get();
@Bean
public KieContainer kieContainer() {
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write(ResourceFactory.newClassPathResource(drl_file_path));
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
KieModule kieModule = kieBuilder.getKieModule();
KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());
return kieContainer;
}
}
9. Create DroolsController.java under the Controller folder
package com.drools.droolspoc.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.drools.droolspoc.Model.OrderDiscount;
import com.drools.droolspoc.Model.OrderRequest;
import com.drools.droolspoc.Service.DroolsService;
@RestController
@RequestMapping("api/v1/drools")
public class DroolsController {
@Autowired
private DroolsService droolsService;
@PostMapping(path = "/getOrderDiscount")
public OrderDiscount getOrderDiscount(@RequestBody OrderRequest orderRequest){
return droolsService.getOrderDiscount(orderRequest);
}
}
10. Create DroolsService.java under the Service folder
package com.drools.droolspoc.Service;
import com.drools.droolspoc.Model.OrderDiscount;
import com.drools.droolspoc.Model.OrderRequest;
public interface DroolsService {
OrderDiscount getOrderDiscount(OrderRequest orderRequest);
}
11. Create DroolsServiceImpl.java under the ServiceImpl folder
package com.drools.droolspoc.ServiceImpl;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.drools.droolspoc.Model.OrderDiscount;
import com.drools.droolspoc.Model.OrderRequest;
import com.drools.droolspoc.Service.DroolsService;
@Service
public class DroolsServiceImpl implements DroolsService{
@Autowired
private KieContainer kieContainer;
@Override
public OrderDiscount getOrderDiscount(OrderRequest orderRequest) {
OrderDiscount orderDiscount = new OrderDiscount();
KieSession kieSession = kieContainer.newKieSession();
kieSession.setGlobal("orderDiscount", orderDiscount);
kieSession.insert(orderRequest);
kieSession.fireAllRules();
kieSession.dispose();
return orderDiscount;
}
}
12. Run the project in VS Code
13. Open SoapUI
The reason behind the discount: 20 –
Thus, we come to the end of the project using Spring Boot, and Drools Rule Engine😊
Thank you for reading! I hope you’re able to understand and proceed with the development of this explanation and if so, please share to help others too. 😊
Well, there are a lot of areas for improvement in this project and, for any new suggestions or comments, I’m all ears.
Download project from: https://github.com/sharuroy16/drools-poc