Drools — Drive your rules from database

Paras Bansal
3 min readJan 29, 2022

Lately we were presented with a requirement on our rules engine app that all the rules should be driven from a database. What basically it meant was we shouldn’t be deploying when there is any changes to the values used to determine rules. The only deployment should when we have a requirement change.

So we thought of a generic rule engine application in which values are fed from database based on the request and the final output is calculated. Here in this post I’ll give an idea on how we implemented. This is a mvp version, and it definitely needs lot of upgrades to implement the idea in a correct way that suits your needs.

Scenario

Suppose there is a discounting app where your system is allowed to a do a final discount based on number of items in the order cart. For e.g. here is your database:

The goal here is to find out the average of discount based on the number of items in the cart. I stored the above data in the mongodb atlas which can be accessed in a spring application using following configuration in application yaml:

spring:
api_user: test
api_password: test
application:
name: spring-rules-processor
server:
port: 8080
data:
mongodb:
uri: mongodb+srv://<user>:<password>@<server>/<db>?retryWrites=true&w=majority
logging.level:
com.company: DEBUG

Once there, include the mongodb dependency in the dependency:

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

Lastly, here is the repository class to access the data:

package com.company.vo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import com.company.vo.Item;import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Repository
@RequiredArgsConstructor
public class MongoRepository {
@Autowired
private final MongoTemplate mongoTemplate;

public Item getItemData(Item item) {
Query query = new Query();
query.addCriteria(new Criteria()
.where("item_id").is(String.valueOf(item.getItem_id()))
.and("date").is(item.getDate())
);

return mongoTemplate.findOne(query, Item.class, "items");
}
}

This corresponds to an Item vo as below:

package com.company.vo;import org.springframework.data.annotation.Id;@lombok.Data
public class Item {
@Id
private String _id;

private String item_id;
private String itemp_description;
private String date;
private Integer three_or_more_item_discount;
private Integer five_or_more_item_discount;
}

So far it was basics. Now it comes to configuring the rules itself. Below is how did it:

A little small image, but you can always refer to excel sheet in the github repo (specified at the end)

So what it does is, queries the data from mongo db for all the items supplied in the list and them uses accumulate to calculate the count and averages of the discounts. Based on number of items, it sets the final discount.

None of the values are hardcoded here (except number of items) and everything is driven from database.

The app also takes in the fact that discounts can change based on date. So if next month any product has to be on a special deal, just database inserts are needed for that particular date and application can supply discounts based on that configuration.

Demo

Input request —

[
{
"item_id": "1",
"date": "2021-01-01"
},
{
"item_id": "2",
"date": "2021-01-01"
},
{
"item_id": "1",
"date": "2021-01-01"
},
{
"item_id": "4",
"date": "2021-01-01"
},
{
"item_id": "6",
"date": "2021-01-01"
}
]

Output —

{
"final_discount": 11
}

This is it for now. Please post your comments and questions and I’ll be happy to respond.

Github: https://github.com/paras301/drools-rules-with-dynamic-updates-from-db

P.S. The app in github uses basic authentication user/password — test/test

--

--