Backend Development 11 min read

Implement Dynamic Discount Rules in Spring Boot with Drools

This guide shows how to integrate the Drools rule engine into a Spring Boot application to calculate e‑commerce discounts dynamically, covering Maven dependencies, configuration, model definitions, DRL rule creation, service and controller layers, and a simple test scenario demonstrating rule‑driven discount computation.

macrozheng
macrozheng
macrozheng
Implement Dynamic Discount Rules in Spring Boot with Drools

Introduction

When an e‑commerce system needs to calculate discounts based on flexible business rules—such as extra 5 % for VIP customers or an additional 10 % for orders over 1000 CNY—hard‑coding the logic would require code changes, retesting and redeployment each time a rule changes. Using a rule engine like Drools allows the rules to be externalised and modified without touching the business code.

Adding Maven Dependencies

Create a Spring Boot project and add the following Drools dependencies to

pom.xml

:

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.drools&lt;/groupId&gt;
  &lt;artifactId&gt;drools-core&lt;/artifactId&gt;
  &lt;version&gt;7.59.0.Final&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.drools&lt;/groupId&gt;
  &lt;artifactId&gt;drools-compiler&lt;/artifactId&gt;
  &lt;version&gt;7.59.0.Final&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.drools&lt;/groupId&gt;
  &lt;artifactId&gt;drools-decisiontables&lt;/artifactId&gt;
  &lt;version&gt;7.59.0.Final&lt;/version&gt;
&lt;/dependency&gt;</code>

Drools Configuration Class

Create a

DroolsConfig

class that registers a

KieContainer

bean and loads the DRL files from

src/main/resources/rules

:

<code>@Configuration
public class DroolsConfig {
    // Path to the rule file
    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());
    }
}</code>

Defines a Spring bean of type

KieContainer

that loads the DRL file from the classpath.

Creates a

KieFileSystem

to write the rule file.

Builds the Drools module with

KieBuilder

.

Exposes the container as a Spring bean.

Business Model Classes

Define the request object, an enum for customer type, and a DTO for the discount result.

<code>@Getter @Setter
public class OrderRequest {
    private String customerNumber;
    private Integer age;
    private Integer amount;
    private CustomerType customerType;
}</code>
<code>public enum CustomerType {
    LOYAL, NEW, DISSATISFIED;
    public String getValue() { return this.toString(); }
}</code>
<code>@Getter @Setter
public class OrderDiscount {
    private Integer discount = 0;
}</code>

Drools Rules (customer-discount.drl)

The DRL file contains four rules that adjust a global

orderDiscount

object.

<code>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 3: Other customer types
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 4: Amount based discount
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</code>

Service Layer

The

OrderDiscountService

obtains a

KieSession

, injects the global discount object, inserts the request, fires all rules and returns the calculated discount.

<code>@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;
    }
}</code>

Controller

Expose a REST endpoint that receives an

OrderRequest

JSON and returns the calculated

OrderDiscount

.

<code>@RestController
public class OrderDiscountController {

    @Autowired
    private OrderDiscountService orderDiscountService;

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

Testing

Run the Spring Boot application and POST a JSON payload such as:

<code>{
  "customerNumber": "C001",
  "age": 18,
  "amount": 1200,
  "customerType": "LOYAL"
}</code>

For a loyal customer younger than 20 with an order amount greater than 1000, the rules above produce a total discount of 20 % (10 % age discount + 5 % loyal‑customer discount + 5 % amount discount).

Conclusion

By integrating Drools with Spring Boot we can externalise discount logic into a DRL file, allowing business users or product managers to add or modify rules—such as a new rule for customers in a specific city—without changing Java code, thus speeding up iteration and reducing deployment risk.

BackendJavarule engineSpring Bootdroolsdiscount
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

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.