Introduction
We will see an example on drools support in Spring Boot 2. We have seen in past example on how to integrate drools in Spring application. We had used Spring Boot version 1.5.9 but here we will support Spring Boot 2.1.5 version. I will not explain about drools in this post and if you want to know on drools then you can check my previous example how to integrate drools in Spring application.
Prerequisites
Eclipse Neon, Java 1.8, Gradle 5.4.1, Drools 7.22.0
Example with Source Code
Creating Project
Create a gradle based project in Eclipse, the project structure may look to the similar image as shown below:

Updating Build File
Update the content of the default generated build.gradle script to include the required dependencies.
We are using Spring Boot 2.1.5 and Drools 7.22.0.
buildscript {
ext {
springBootVersion = '2.1.5.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
//Drools and KIE components
compile("org.kie:kie-spring:7.22.0.Final")
compile("org.drools:drools-compiler:7.22.0.Final")
}
Drools Configuration
We want to use Java based configurations so create below java class to create all the required configurations. We will put all rule files under src/main/resources/rules directory.
We have defined few beans for our Spring and Drools integration.
We have created KieFileSystem bean that finds all the rule files put under the classpath file system. These rule files define the rules, which would be applied on the object fields for validation.
We have defined KieContainer bean which is used to create different components, such as, KieSession that is required to create before fire rules on the drools file.
package com.roytuts.spring.drools.config;
import java.io.IOException;
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.builder.KieRepository;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
@Configuration
public class SpringDroolsConfig {
private static final String RULES_PATH = "rules/";
@Bean
public KieFileSystem kieFileSystem() throws IOException {
KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
for (Resource file : getRuleFiles()) {
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
}
return kieFileSystem;
}
private Resource[] getRuleFiles() throws IOException {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
}
@Bean
public KieContainer kieContainer() throws IOException {
final KieRepository kieRepository = getKieServices().getRepository();
kieRepository.addKieModule(new KieModule() {
public ReleaseId getReleaseId() {
return kieRepository.getDefaultReleaseId();
}
});
KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
kieBuilder.buildAll();
return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
}
private KieServices getKieServices() {
return KieServices.Factory.get();
}
}
Creating Custom Exception
We will create custom exception class to throw exception when validation fails. We will create NumberFormatException class to throw number format exception for non-integer value.
package com.roytuts.spring.drools.exception;
public class NumberFormatException extends RuntimeException {
private static final long serialVersionUID = 1L;
public NumberFormatException(String msg) {
super(msg);
}
}
Creating Vo Class
We will create VO class to use on REST controller.
We will apply validation on code using drools.
package com.roytuts.spring.drools.vo;
public class AreaPin {
private int code;
public AreaPin(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
Creating Rule Validate File
Create a file called PinCodeValidation.drl to perform validation on pin code. We will check whether the pin code is 6 digits integer value or not.
The rule validation file must be put into src/main/resources/rules folder as we mentioned earlier. You may put into other location and accordingly you have to change the configuration.
You find AreaPin in when clause is the object and field code is accessed directly by its property name in the AreaPin class.
package com.roytuts.spring.drools.rules
import com.roytuts.spring.drools.vo.AreaPin;
import com.roytuts.spring.drools.exception.NumberFormatException;
rule "PinCodeValidation"
when
AreaPin(code != 0 && code not matches "^[0-9]{6}$")
then
throw new NumberFormatException("Invalid Area Pin Code. Must be a valid 6 digits number.");
end
Creating REST Controller
The Spring REST controller that handles end users requests/responses is given below.
We want to search the area name for a given pin code using REST service. So before we search into the Map whether the area name will be returned or not, we perform validation on pin code and rule is fired using drools.
Notice how we autowire KieContainer and create KieSession and fire the rule on AreaPin object.
If pin code validation fails then you will see exception in the console as well as on the web page or REST client.
If pin code validation passes then area name will be returned if found or Area not found message will e returned as a default value from the Map.
package com.roytuts.spring.drools.rest.controller;
import java.util.HashMap;
import java.util.Map;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.roytuts.spring.drools.vo.AreaPin;
@RestController
public class AreaRestController {
@Autowired
private KieContainer kieContainer;
@GetMapping("/area/name/{pinCode}")
public ResponseEntity<String> getAreaByPinCode(@PathVariable int pinCode) {
KieSession kieSession = kieContainer.newKieSession();
kieSession.insert(new AreaPin(pinCode)); // which object to validate
kieSession.fireAllRules(); // fire all rules defined into drool file (drl)
kieSession.dispose();
return new ResponseEntity<String>(getAreaByCode(pinCode), HttpStatus.OK);
}
private String getAreaByCode(int pin) {
final Map<Integer, String> areaMap = new HashMap<>();
areaMap.put(700001, "BBD Bag");
areaMap.put(700010, "Beliaghata");
areaMap.put(700105, "Nabapally");
areaMap.put(700098, "Sukanta Nagar");
return areaMap.getOrDefault(pin, "Area not found");
}
}
Creating Main Class
A class with main method and @SpringBootApplication is enough to start the Spring Boot application.
package com.roytuts.spring.drools;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.roytuts.spring.drools")
public class SpringBoot2Drools {
public static void main(String[] args) {
SpringApplication.run(SpringBoot2Drools.class, args);
}
}
Testing the Application
Run the above main class to deploy into Tomcat server and start the application.
Once the application deployed, it starts on port number 8080 as it is a default port of Tomcat. You may also override this port number in application.properties or application.yml file using key server.port.
If you hit below URL, you will get below output on the browser

If you hit below URL, you will see below exception on page as well in console.

Console error is given below:
[Request processing failed; nested exception is Exception executing consequence for rule "PinCodeValidation" in com.roytuts.spring.drools.rules: com.roytuts.spring.drools.exception.NumberFormatException: Invalid Area Pin Code. Must be a valid 6 digits number.]
Source Code
Thanks for reading.