Backend Development 9 min read

Implementing Discount Calculation with Drools Rule Engine in a Spring Boot Application

This tutorial explains how to integrate the Drools business rule engine into a Spring Boot project to calculate flexible e‑commerce discounts based on customer type, age, and order amount, showing dependency setup, configuration, model definitions, DRL rules, service and controller layers, and a test run.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing Discount Calculation with Drools Rule Engine in a Spring Boot Application

In this article, the author demonstrates how to use the Drools business rule engine to implement flexible discount calculation for e‑commerce orders in a Spring Boot application.

First, the required Drools dependencies (drools‑core, drools‑compiler, drools‑decisiontables) are added to the Maven pom.xml :

<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-core</artifactId>
  <version>7.59.0.Final</version>
</dependency>
<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-compiler</artifactId>
  <version>7.59.0.Final</version>
</dependency>
<dependency>
  <groupId>org.drools</groupId>
  <artifactId>drools-decisiontables</artifactId>
  <version>7.59.0.Final</version>
</dependency>

A @Configuration class DroolsConfig creates a Spring bean of type KieContainer that loads the DRL files from the classpath:

@Configuration
public class DroolsConfig {
    private static final String RULES_CUSTOMER_RULES_DRL = "rules/customer-discount.drl";
    private static final KieServices kieServices = KieServices.Factory.get();

    @Bean
    public KieContainer kieContainer() {
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));
        KieBuilder kb = kieServices.newKieBuilder(kieFileSystem);
        kb.buildAll();
        KieModule kieModule = kb.getKieModule();
        return kieServices.newKieContainer(kieModule.getReleaseId());
    }
}

Domain models OrderRequest , CustomerType enum, and OrderDiscount are defined to carry the input data and the computed discount:

@Getter
@Setter
public class OrderRequest {
    private String customerNumber;
    private Integer age;
    private Integer amount;
    private CustomerType customerType;
}

public enum CustomerType {
    LOYAL, NEW, DISSATISFIED;
    public String getValue() { return this.toString(); }
}

@Getter
@Setter
public class OrderDiscount {
    private Integer discount = 0;
}

The DRL file customer-discount.drl contains four rules: age‑based discount, loyal‑customer discount, other‑customer discount, and amount‑based discount, each adding a percentage to a global orderDiscount object:

import com.alvin.drools.model.OrderRequest;
import com.alvin.drools.model.CustomerType;

global com.alvin.drools.model.OrderDiscount orderDiscount;

dialect "mvel"

// Rule 1: Age based discount
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 2: Loyal customer discount
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 > 1000L)
    then
        System.out.println("==========Adding 5% discount for amount more than 1000$=============");
        orderDiscount.setDiscount(orderDiscount.getDiscount() + 5);
end

A service class OrderDiscountService obtains a KieSession from the container, sets the global discount object, inserts the OrderRequest , fires all rules and returns the resulting OrderDiscount :

@Service
public class OrderDiscountService {

    @Autowired
    private KieContainer kieContainer;

    public OrderDiscount getDiscount(OrderRequest orderRequest) {
        OrderDiscount orderDiscount = new OrderDiscount();
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.setGlobal("orderDiscount", orderDiscount);
        kieSession.insert(orderRequest);
        kieSession.fireAllRules();
        kieSession.dispose();
        return orderDiscount;
    }
}

The REST controller OrderDiscountController exposes a POST endpoint /get-discount that receives an OrderRequest JSON payload and returns the calculated discount:

@RestController
public class OrderDiscountController {

    @Autowired
    private OrderDiscountService orderDiscountService;

    @PostMapping("/get-discount")
    public ResponseEntity
getDiscount(@RequestBody OrderRequest orderRequest) {
        OrderDiscount discount = orderDiscountService.getDiscount(orderRequest);
        return new ResponseEntity<>(discount, HttpStatus.OK);
    }
}

Running the Spring Boot application and sending a sample request (e.g., a loyal customer under 20 years old with amount > 1000) yields a combined 20 % discount, confirming that the rule engine works as expected.

The article concludes that Drools provides a simple way to externalize discount logic, allowing business users to add or modify rules without changing Java code, though the author humorously notes that this can also be used for “slacking off”.

Javarule enginebackend developmentSpring BootdroolsDiscount Calculation
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.