Configure Kie Business Central To Use MySQL DataBase

Prerequisites

Install required artifacts

Configure

Start the server

standalone.bat -Dorg.kie.server.id=boot-kie-server-Dorg.kie.server.id=first-kie-server -Dorg.kie.server.location=http://localhost:8090/rest/server -Dorg.kie.server.user=kieserver -Dorg.kie.server.password=kieserver1! -Dorg.jbpm.server.ext.disabled=true -Dorg.kie.server.controller=http://localhost:8080/business-central/rest/controller -Dorg.kie.server.persistence.dialect=org.hibernate.dialect.MySQL8Dialect -Dorg.kie.server.persistence.ds=java:jboss/datasources/MySql8DS

Key Things

-Dorg.kie.server.persistence.dialect=org.hibernate.dialect.MySQL8Dialect

-Dorg.kie.server.persistence.ds=java:jboss/datasources/MySql8DS

References

Also See

Creating Rules Using Drools KIE Workbench / Business Central And Running In Kie Server

Preliminary

Start the Workbench and KIE Server

Rule Creation

Creating Project

General Settings

Metrics

Add Assets

Model

DRL

package com.myspace.demorule;

import com.myspace.demorule.Sale;

  
rule "DiscountForCarSale"
    when
        thisSale : Sale (quantity >= 5 , item == "Car");
    then
        thisSale.setDiscount(10);
end;
  
rule "DiscountForBikeSale"
    when
        thisSale : Sale (quantity >= 10 , item == "Bike");
    then
        thisSale.setDiscount(15);
end;

Make sure to validate by clicking on validate button

Build & Install

Deploy

Deployment added

Kie Server logs

2021-05-13 06:26:51.835  INFO 9516 --- [0.1-8090-exec-6] o.d.c.kie.builder.impl.KieContainerImpl  : End creation of KieBase: defaultKieBase
2021-05-13 06:26:51.836  INFO 9516 --- [0.1-8090-exec-6] o.k.s.s.jbpm.JbpmKieServerExtension      : Container drools-demo-kjar_1.0.0-SNAPSHOT does not include processes, jBPM KIE Server extension skipped
2021-05-13 06:26:51.837  INFO 9516 --- [0.1-8090-exec-6] o.k.server.services.impl.KieServerImpl   : Container drools-demo-kjar_1.0.0-SNAPSHOT (for release id com.github.mnadeem:drools-demo-kjar:1.0.0-SNAPSHOT) successfully started

Testing Our Rule

Get the containers

curl --location --request GET 'http://localhost:8090/rest/server/containers' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \
--header 'Cookie: JSESSIONID=023592B1C7DC41AC30AD5A7D868BDE10'

Execute Rule

Request body

curl --location --request POST 'http://localhost:8090/rest/server/containers/instances/drools-demo-kjar_1.0.0-SNAPSHOT' \
--header 'Content-Type: application/json' \
--header 'X-KIE-ContentType: JSON' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \
--header 'Cookie: JSESSIONID=023592B1C7DC41AC30AD5A7D868BDE10' \
--data-raw '{
  "lookup" : null,
  "commands" : [ {
    "insert" : {
      "object" : {"com.myspace.demorule.Sale":{
  "quantity" : 100,
  "item" : "Car"
}},
      "out-identifier" : "Sale",
      "return-object" : true,
      "entry-point" : "DEFAULT",
      "disconnected" : false
    }
  }, {
    "fire-all-rules" : {
      "max" : -1,
      "out-identifier" : null
    }
  } ]
}'

Source Code

Also See

References

Kie Business Central Workbench Up And Running In Windows Machine

Download Artificats

business-central

wildfly-dist

Setup

Extract

Rename business-central-7.53.0.Final-wildfly19.war to business-central.war and paste it over, WILDFLY_HOME\business-central

Increase memory

JAVA_OPTS=-Xms1024M -Xmx2048M -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=512m

Add User

admin,manager,user,analyst,developer,kie-server

Start

Execute standalone.bat

Workbench started

Access http://localhost:8080/business-central

Using Maven Project

I have created a maven project, which would automate some of these things (Downloading artifacts, extracting, renaming and copying, etc)

Download the project and do execute mvn clean package

artifacts downloaded and extracted in target folder

war file copied and renamed

Run the standalone.bat file

Using Docker

https://hub.docker.com/r/jboss/business-central-workbench-showcase/

https://hub.docker.com/r/jboss/jbpm-server-full

Kie Server Integration

Make sure Kie Server Started

Start business-central using the following command

standalone.bat  -Dorg.kie.server.id=boot-kie-server-Dorg.kie.server.id=first-kie-server  -Dorg.kie.server.location=http://localhost:8090/rest/server -Dorg.kie.server.user=kieserver -Dorg.kie.server.password=kieserver1! -Dorg.jbpm.server.ext.disabled=true -Dorg.kie.server.controller=http://localhost:8080/business-central/rest/controller

for full-xml

standalone.bat -c standalone-full.xml  -Dorg.kie.server.id=boot-kie-server-Dorg.kie.server.id=first-kie-server  -Dorg.kie.server.location=http://localhost:8090/rest/server -Dorg.kie.server.user=kieserver -Dorg.kie.server.password=kieserver1! -Dorg.jbpm.server.ext.disabled=true -Dorg.kie.server.controller=http://localhost:8080/business-central/rest/controller

Once The Kie Server is up, it would automatically show here

Source Code

Also See

References

Executing Rules On KieServer From Spring Boot Application : Drools As A Service

Start the Kie Server

Follow this to start it.

Kie Server Started

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.4.RELEASE)

2021-05-11 05:16:27.421  INFO 6868 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : Starting BootJbpmKieServerApplication on DESKTOP-9AES3TT with PID 6868 (E:\eWorkspaces\drools\boot-jbpm-kie-server\target\classes started by reach in E:\eWorkspaces\drools\boot-jbpm-kie-server)
2021-05-11 05:16:27.424  INFO 6868 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : No active profile set, falling back to default profiles: default
2021-05-11 05:16:28.872  INFO 6868 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8090 (http)
2021-05-11 05:16:28.887  INFO 6868 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-11 05:16:28.887  INFO 6868 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.38]
2021-05-11 05:16:29.073  INFO 6868 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-11 05:16:29.073  INFO 6868 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1607 ms
2021-05-11 05:16:29.422  WARN 6868 --- [           main] com.arjuna.ats.common                    : ARJUNA048002: Could not find configuration file, URL was: null
2021-05-11 05:16:29.509  INFO 6868 --- [           main] o.d.p.api.TransactionManagerFactory      : Using org.kie.spring.persistence.KieSpringTransactionManagerFactory@559d19c
2021-05-11 05:16:29.535  INFO 6868 --- [           main] com.arjuna.ats.jbossatx                  : ARJUNA032010: JBossTS Recovery Service (tag: 92f28891fd5f29d0381da214d4f3a2917f46e301) - JBoss Inc.
2021-05-11 05:16:29.577  INFO 6868 --- [           main] com.arjuna.ats.jbossatx                  : ARJUNA032013: Starting transaction recovery manager
2021-05-11 05:16:29.742  INFO 6868 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: org.jbpm.domain]
2021-05-11 05:16:29.821  INFO 6868 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.21.Final
2021-05-11 05:16:30.019  INFO 6868 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2021-05-11 05:16:31.011  INFO 6868 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2021-05-11 05:16:31.501  INFO 6868 --- [           main] org.hibernate.orm.beans                  : HHH10005002: No explicit CDI BeanManager reference was passed to Hibernate, but CDI is available on the Hibernate ClassLoader.
2021-05-11 05:16:31.615  INFO 6868 --- [d Entry Monitor] com.arjuna.ats.arjuna                    : ARJUNA012332: Failed to establish connection to server
2021-05-11 05:16:32.262  INFO 6868 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform]
2021-05-11 05:16:32.787  WARN 6868 --- [           main] o.h.dialect.function.TemplateRenderer    : HHH000174: Function template anticipated 4 arguments, but 1 arguments encountered
2021-05-11 05:16:32.787  WARN 6868 --- [           main] o.h.dialect.function.TemplateRenderer    : HHH000174: Function template anticipated 4 arguments, but 1 arguments encountered
2021-05-11 05:16:32.838  INFO 6868 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'org.jbpm.domain'
2021-05-11 05:16:32.881  WARN 6868 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-05-11 05:16:33.163  INFO 6868 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4690cb47, org.springframework.security.web.context.SecurityContextPersistenceFilter@5e91b051, org.springframework.security.web.header.HeaderWriterFilter@751636da, org.springframework.security.web.authentication.logout.LogoutFilter@16908f89, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@55fbebba, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@77376e83, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@1b204439, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@77d80294, org.springframework.security.web.session.SessionManagementFilter@3d5a6849, org.springframework.security.web.access.ExceptionTranslationFilter@28068327, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@16c9ec5b]
2021-05-11 05:16:33.253  INFO 6868 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-11 05:16:33.692  INFO 6868 --- [           main] o.k.i.pmml.PMMLImplementationsUtil       : Using NEW implementation
2021-05-11 05:16:33.692  INFO 6868 --- [           main] o.k.i.pmml.PMMLImplementationsUtil       : Using NEW implementation
2021-05-11 05:16:33.877  INFO 6868 --- [           main] com.arjuna.ats.arjuna                    : ARJUNA012170: TransactionStatusManager started on port 58892 and host 127.0.0.1 with service com.arjuna.ats.arjuna.recovery.ActionStatusService
2021-05-11 05:16:34.265  INFO 6868 --- [           main] o.k.s.s.a.KieServerAutoConfiguration     : KieServer (id boot-kie-server (name KIE Server SpringBoot)) started initialization process
2021-05-11 05:16:34.482  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Starting server in 'DEVELOPMENT' mode.
2021-05-11 05:16:34.485  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Selected startup strategy ControllerBasedStartupStrategy - deploys kie containers given by controller ignoring locally defined
2021-05-11 05:16:34.486  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Configured 'KieServerStateFileRepository' server state repository
2021-05-11 05:16:34.515  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Server Default Extension has been successfully registered as server extension
2021-05-11 05:16:34.516  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Drools KIE Server extension has been successfully registered as server extension
2021-05-11 05:16:34.535  INFO 6868 --- [           main] o.k.s.api.marshalling.MarshallerFactory  : Marshaller extensions init
2021-05-11 05:16:34.546  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : jBPM KIE Server extension has been successfully registered as server extension
2021-05-11 05:16:34.548  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Case-Mgmt KIE Server extension has been successfully registered as server extension
2021-05-11 05:16:34.655  INFO 6868 --- [           main] o.k.s.s.j.u.f.r.BootstrapFormRenderer    : Boostrap Form renderer templates loaded successfully.
2021-05-11 05:16:34.660  INFO 6868 --- [           main] o.k.s.s.j.u.f.r.PatternflyFormRenderer   : patternfly Form renderer templates loaded successfully.
2021-05-11 05:16:34.666  INFO 6868 --- [           main] o.k.s.s.j.u.f.r.PatternflyFormRenderer   : workbench Form renderer templates loaded successfully.
2021-05-11 05:16:34.667  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : jBPM-UI KIE Server extension has been successfully registered as server extension
2021-05-11 05:16:34.670  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : DMN KIE Server extension has been successfully registered as server extension
2021-05-11 05:16:34.672  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Scenario Simulation KIE Server extension has been successfully registered as server extension
2021-05-11 05:16:34.674  INFO 6868 --- [           main] o.k.s.s.impl.policy.PolicyManager        : Registered KeepLatestContainerOnlyPolicy{interval=0 ms} policy under name KeepLatestOnly
2021-05-11 05:16:34.674  INFO 6868 --- [           main] o.k.s.s.impl.policy.PolicyManager        : Policy manager started successfully, activated policies are []
2021-05-11 05:16:34.678  INFO 6868 --- [           main] o.k.s.services.impl.ContainerManager     : About to install containers on kie server 
	KieServer{id='boot-kie-server'name='KIE Server SpringBoot'version='7.53.0.Final'location='http://localhost:8090/rest/server'}:
	KieContainerResource [containerId=my-deploy, releaseId=com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT, resolvedReleaseId=null, status=STARTED]
	KieContainerResource [containerId=testFirstContainer, releaseId=com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT, resolvedReleaseId=null, status=STARTED]
2021-05-11 05:16:35.839  INFO 6868 --- [           main] o.d.c.k.b.i.InternalKieModuleProvider    : Creating KieModule for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT
2021-05-11 05:16:35.847  INFO 6868 --- [           main] o.d.m.CanonicalKieModuleProvider         : No executable model found for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT. Falling back to resources parsing.
2021-05-11 05:16:35.956  INFO 6868 --- [           main] o.d.c.kie.builder.impl.KieContainerImpl  : Start creation of KieBase: defaultKieBase
2021-05-11 05:16:36.644  INFO 6868 --- [           main] o.d.c.kie.builder.impl.KieContainerImpl  : End creation of KieBase: defaultKieBase
2021-05-11 05:16:36.645  INFO 6868 --- [           main] o.k.s.s.jbpm.JbpmKieServerExtension      : Container my-deploy does not include processes, jBPM KIE Server extension skipped
2021-05-11 05:16:36.646  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Container my-deploy (for release id com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT) successfully started
2021-05-11 05:16:36.656  WARN 6868 --- [           main] o.k.s.s.i.c.DefaultRestControllerImpl    : No controllers found to update to new status org.kie.server.api.model.KieServerStateInfo@6983436f
2021-05-11 05:16:36.732  INFO 6868 --- [           main] o.d.c.k.b.i.InternalKieModuleProvider    : Creating KieModule for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT
2021-05-11 05:16:36.732  INFO 6868 --- [           main] o.d.m.CanonicalKieModuleProvider         : No executable model found for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT. Falling back to resources parsing.
2021-05-11 05:16:36.793  INFO 6868 --- [           main] o.d.c.kie.builder.impl.KieContainerImpl  : Start creation of KieBase: defaultKieBase
2021-05-11 05:16:36.849  INFO 6868 --- [           main] o.d.c.kie.builder.impl.KieContainerImpl  : End creation of KieBase: defaultKieBase
2021-05-11 05:16:36.849  INFO 6868 --- [           main] o.k.s.s.jbpm.JbpmKieServerExtension      : Container testFirstContainer does not include processes, jBPM KIE Server extension skipped
2021-05-11 05:16:36.907  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : Container testFirstContainer (for release id com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT) successfully started
2021-05-11 05:16:36.909  WARN 6868 --- [           main] o.k.s.s.i.c.DefaultRestControllerImpl    : No controllers found to update to new status org.kie.server.api.model.KieServerStateInfo@16ee0c8f
2021-05-11 05:16:36.912  INFO 6868 --- [           main] o.k.server.services.impl.KieServerImpl   : KieServer boot-kie-server is ready to receive requests
2021-05-11 05:16:36.950  INFO 6868 --- [           main] o.k.s.s.a.KieServerAutoConfiguration     : KieServer (id boot-kie-server) started successfully
2021-05-11 05:16:37.164  INFO 6868 --- [           main] org.apache.cxf.endpoint.ServerImpl       : Setting the server's publish address to be /
2021-05-11 05:16:37.330  INFO 6868 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8090 (http) with context path ''
2021-05-11 05:16:37.339  INFO 6868 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : Started BootJbpmKieServerApplication in 10.235 seconds (JVM running for 10.785)

Client App

https://start.spring.io/

Add the following to pom

		<dependency>
            <groupId>org.kie.server</groupId>
            <artifactId>kie-server-client</artifactId>
            <version>${kie.version}</version>
        </dependency>

And change the boot version to 2.3.4.RELEASE, since kie 7.53.0.Final uses it.

Complete pom file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.github.mnadeem</groupId>
	<artifactId>boot-drools-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>boot-drools-service</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<kie.version>7.53.0.Final</kie.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
            <groupId>org.kie.server</groupId>
            <artifactId>kie-server-client</artifactId>
            <version>${kie.version}</version>
        </dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Sale.java

package com.github.mnadeem.discount.model;

public class Sale {
    
    private int quantity;
    private String item;
    private int discount;
  
    public int getQuantity() {
        return quantity;
    }
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public int getDiscount() {
        return discount;
    }
    public void setDiscount(int discount) {
        this.discount = discount;
    }
	@Override
	public String toString() {
		return "Sale [quantity=" + quantity + ", item=" + item + ", discount=" + discount + "]";
	}
}

application.properties

kie.containerId=my-deploy
kie.server.user=kieserver
kie.server.password=kieserver1!
kie.server.url=http://localhost:8090/rest/server

DiscountService.java

package com.github.mnadeem.discount;

import java.util.ArrayList;
import java.util.List;

import org.kie.api.KieServices;
import org.kie.api.command.BatchExecutionCommand;
import org.kie.api.command.Command;
import org.kie.api.command.KieCommands;
import org.kie.api.runtime.ExecutionResults;
import org.kie.internal.command.CommandFactory;
import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.api.model.ServiceResponse;
import org.kie.server.client.KieServicesConfiguration;
import org.kie.server.client.KieServicesFactory;
import org.kie.server.client.RuleServicesClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.github.mnadeem.discount.model.Sale;

@Service
public class DiscountService {

    private static final String SALE_IDENTIFIER = "Sale";
    
    private static final Logger LOGGER = LoggerFactory.getLogger(DiscountService.class);

    @Value("${kie.containerId}")
	private String containerId;
    @Value("${kie.server.user}")
    private String user;
    @Value("${kie.server.password}")
    private String password;
    @Value("${kie.server.url}")
    private String url;

	public void applyDiscount(Sale sale) {

		KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(url, user, password, 60000);
        config.setMarshallingFormat(MarshallingFormat.JSON);

		RuleServicesClient client = KieServicesFactory.newKieServicesClient(config).getServicesClient(RuleServicesClient.class);
		BatchExecutionCommand batchExecutionCommand = batchCommand(sale);
		ServiceResponse<ExecutionResults> response = client.executeCommandsWithResults(containerId, batchExecutionCommand);
 
		if (response.getType() == ServiceResponse.ResponseType.SUCCESS) {
			LOGGER.info("Commands executed with success! Response: ");
			LOGGER.info("{}", response.getResult());
			Sale saleUpdated = (Sale) response.getResult().getValue(SALE_IDENTIFIER);
			sale.setDiscount(saleUpdated.getDiscount());
			LOGGER.info("{}", saleUpdated);
		} else {
			LOGGER.error("Error executing rules. Message: {}", response.getMsg());
		}
	}

	private BatchExecutionCommand batchCommand(Sale sale) {
		List<Command<?>> cmds = buildCommands(sale);

		BatchExecutionCommand batchExecutionCommand = CommandFactory.newBatchExecution(cmds);
		return batchExecutionCommand;
	}

	private List<Command<?>> buildCommands(Sale sale) {
		List<Command<?>> cmds = new ArrayList<Command<?>>();
		KieCommands commands = KieServices.Factory.get().getCommands();

		cmds.add(commands.newInsert(sale, SALE_IDENTIFIER));
		cmds.add(commands.newFireAllRules());
		return cmds;
	}
}

DiscountController.java

package com.github.mnadeem.discount;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.github.mnadeem.discount.model.Sale;

@RestController
public class DiscountController {

	private DiscountService discountService;

	public DiscountController(DiscountService service) {
		this.discountService = service;
	}

	@PostMapping("/discount")
	private Sale getDiscountPercent(@RequestBody Sale sale) {		
		this.discountService.applyDiscount(sale);
	    return sale;
	}
}

Start the App

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.4.RELEASE)

2021-05-11 05:55:29.100  INFO 10160 --- [           main] c.g.m.BootDroolsServiceApplication       : Starting BootDroolsServiceApplication on DESKTOP-9AES3TT with PID 10160 (E:\eWorkspaces\drools\boot-drools-service\target\classes started by reach in E:\eWorkspaces\drools\boot-drools-service)
2021-05-11 05:55:29.103  INFO 10160 --- [           main] c.g.m.BootDroolsServiceApplication       : No active profile set, falling back to default profiles: default
2021-05-11 05:55:29.831  INFO 10160 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-05-11 05:55:29.842  INFO 10160 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-11 05:55:29.843  INFO 10160 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.38]
2021-05-11 05:55:29.946  INFO 10160 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-11 05:55:29.946  INFO 10160 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 805 ms
2021-05-11 05:55:30.086  INFO 10160 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-11 05:55:30.212  INFO 10160 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-11 05:55:30.220  INFO 10160 --- [           main] c.g.m.BootDroolsServiceApplication       : Started BootDroolsServiceApplication in 1.39 seconds (JVM running for 1.756)
2021-05-11 05:55:30.236  INFO 10160 --- [           main] o.k.s.api.marshalling.MarshallerFactory  : Marshaller extensions init
2021-05-11 05:55:33.693  INFO 10160 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-05-11 05:55:33.693  INFO 10160 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-05-11 05:55:33.696  INFO 10160 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms

Invoke The Service

2021-05-11 05:55:39.027  INFO 10160 --- [nio-8080-exec-3] c.g.mnadeem.discount.DiscountService     : Commands executed with success! Response: 
2021-05-11 05:55:39.027  INFO 10160 --- [nio-8080-exec-3] c.g.mnadeem.discount.DiscountService     : org.drools.core.runtime.impl.ExecutionResultImpl@20f12e5b
2021-05-11 05:55:39.027  INFO 10160 --- [nio-8080-exec-3] c.g.mnadeem.discount.DiscountService     : Sale [quantity=100, item=Car, discount=10]

Also See

Source Code

Various Approaches To Embed Drools in Spring Boot Application

There are couple of options to define the scope of the resources and configurations that will be included in an instance of KieContainer.

  • Based of KieFileSystem, we have seen this approach earlier.
  • Based on classpath : will look at all the business assets in the application classpath and allow us to load them in different instances of the rule engine.
  • Based on Maven dependency resolution techniques (KIE-CI) : Will delegate the responsibility of finding out the predefined artifacts and their transitive dependencies into Maven to find out all the resources that need to be included.

Create KieModule

Add the properties section in pom.xml

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

Create META-INF folder

Lets further create the following files

Sale.java

package com.github.mnadeem.discount.model;

public class Sale {
    
    private int quantity;
    private String item;
    private int discount;
 
    public int getQuantity() {
        return quantity;
    }
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public int getDiscount() {
        return discount;
    }
    public void setDiscount(int discount) {
        this.discount = discount;
    }   
}

kmodule.xml

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://jboss.org/kie/6.0.0/kmodule">

</kmodule>

discount.drl

package rules;
 
import com.github.mnadeem.discount.model.Sale;
 
rule "DiscountForCarSale"
    when
        thisSale : Sale (quantity >= 5 , item == "Car");
    then
        thisSale.setDiscount(10);
end;
 
rule "DiscountForBikeSale"
    when
        thisSale : Sale (quantity >= 10 , item == "Bike");
    then
        thisSale.setDiscount(15);
end;

This would create drools-discount-kjar-0.0.1-SNAPSHOT.jar

Loading Rules From Classpath

https://start.spring.io/

Add the following two dependencies

		<dependency>
		    <groupId>org.drools</groupId>
		    <artifactId>drools-core</artifactId>
		    <version>${kie.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.kie</groupId>
		    <artifactId>kie-spring</artifactId>
		    <version>${kie.version}</version>
		</dependency>

kie.version == 7.53.0.Final

Since kie 7.53.0.FINAL uses spring boot 2.3.4.RELEASE, lets switch to this version of boot.

Further add the kjar dependency we have just installed, so that it is available in classpath

		<dependency>
			<groupId>com.github.mnadeem</groupId>
			<artifactId>drools-discount-kjar</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

Complete pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	
	<groupId>com.github.mnadeem</groupId>
	<artifactId>boot-drools-classpath</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>boot-drools-classpath</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<java.version>1.8</java.version>
		<kie.version>7.53.0.Final</kie.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.drools</groupId>
		    <artifactId>drools-core</artifactId>
		    <version>${kie.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.kie</groupId>
		    <artifactId>kie-spring</artifactId>
		    <version>${kie.version}</version>
		</dependency>

		<dependency>
			<groupId>com.github.mnadeem</groupId>
			<artifactId>drools-discount-kjar</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

DroolsConfig.java

package com.github.mnadeem.config;

import java.io.IOException;

import org.kie.api.KieServices;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DroolsConfig {

	private static final Logger LOGGER = LoggerFactory.getLogger(DroolsConfig.class);

	@Bean
	public KieContainer kieContainer() throws IOException {

		KieContainer kContainer = kieServices().newKieClasspathContainer();
		// Let's verify that all the resources are loaded correctly
		Results results = kContainer.verify();
		results.getMessages().stream().forEach((message) -> {
			LOGGER.info(">> Message ( {} ): {}", message.getLevel(), message.getText());
		});
		// If there is an Error we need to stop and correct it
		boolean hasError = results.hasMessages(Message.Level.ERROR);
		LOGGER.info("Any Error : {}", hasError);
		if (hasError) {
			throw new UnsupportedOperationException();
		}
		// Here we make sure that all the KieBases and KieSessions
		// that we are expecting are loaded.
		kContainer.getKieBaseNames().stream().map((kieBase) -> {
			LOGGER.info(">> Loading KieBase: {}", kieBase);
			return kieBase;
		}).forEach((kieBase) -> {
			kContainer.getKieSessionNamesInKieBase(kieBase).stream().forEach((kieSession) -> {
				LOGGER.info("\t >> Containing KieSession: {}", kieSession);
			});
		});

		return kContainer;
	}

	private KieServices kieServices() {
		return KieServices.Factory.get();
	}
}

DiscountService.java

package com.github.mnadeem.discount;

import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.stereotype.Service;
 
import com.github.mnadeem.discount.model.Sale;
 
@Service
public class DiscountService {
 
    private final KieContainer kieContainer;
 
    public DiscountService(KieContainer kieContainer) {
        this.kieContainer = kieContainer;
    }
 
    public void applyDiscount(Sale sale) {
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.insert(sale);
        kieSession.fireAllRules();
        kieSession.dispose();
    }
}

DiscountController.java

package com.github.mnadeem.discount;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
 
import com.github.mnadeem.discount.model.Sale;
 
@RestController
public class DiscountController {
 
    private DiscountService discountService;
 
    public DiscountController(DiscountService service) {
        this.discountService = service;
    }
 
    @PostMapping("/discount")
    private Sale getDiscountPercent(@RequestBody Sale sale) {       
        this.discountService.applyDiscount(sale);
        return sale;
    }
}

Run The application

Output

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.4.RELEASE)

2021-05-10 16:30:54.030  INFO 15572 --- [           main] c.g.m.BootDroolsClasspathApplication     : Starting BootDroolsClasspathApplication on LHTU05CG9234T82 with PID 15572 (C:\Users\reach\eclipse-workspace\2020\drools\boot-drools-classpath\target\classes started by mnadeem6 in C:\Users\reach\eclipse-workspace\2020\drools\boot-drools-classpath)
2021-05-10 16:30:54.034  INFO 15572 --- [           main] c.g.m.BootDroolsClasspathApplication     : No active profile set, falling back to default profiles: default
2021-05-10 16:31:00.315  INFO 15572 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-05-10 16:31:00.336  INFO 15572 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-10 16:31:00.336  INFO 15572 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.38]
2021-05-10 16:31:00.577  INFO 15572 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-10 16:31:00.577  INFO 15572 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 6467 ms
2021-05-10 16:31:01.002  INFO 15572 --- [           main] o.d.c.k.b.impl.ClasspathKieProject       : Found kmodule: file:/C:/Users/reach/eclipse-workspace/2020/drools/drools-discount-kjar/target/classes/META-INF/kmodule.xml
2021-05-10 16:31:01.374  INFO 15572 --- [           main] o.d.c.k.b.i.InternalKieModuleProvider    : Creating KieModule for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT
2021-05-10 16:31:01.381  INFO 15572 --- [           main] o.d.m.CanonicalKieModuleProvider         : No executable model found for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT. Falling back to resources parsing.
2021-05-10 16:31:02.753  INFO 15572 --- [           main] com.github.mnadeem.config.DroolsConfig   : Any Error : false
2021-05-10 16:31:02.755  INFO 15572 --- [           main] com.github.mnadeem.config.DroolsConfig   : >> Loading KieBase: defaultKieBase
2021-05-10 16:31:02.756  INFO 15572 --- [           main] com.github.mnadeem.config.DroolsConfig   : 	 >> Containing KieSession: defaultStatelessKieSession
2021-05-10 16:31:02.756  INFO 15572 --- [           main] com.github.mnadeem.config.DroolsConfig   : 	 >> Containing KieSession: defaultKieSession
2021-05-10 16:31:02.947  INFO 15572 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-10 16:31:03.246  INFO 15572 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-10 16:31:03.261  INFO 15572 --- [           main] c.g.m.BootDroolsClasspathApplication     : Started BootDroolsClasspathApplication in 9.722 seconds (JVM running for 11.097)

Invoke

curl --location --request POST 'localhost:8080/discount' \
--header 'Content-Type: application/json' \
--data-raw '{
    "quantity": 11,
    "item": "Car"
}'

When we create a new KieContainer based on the classpath, all the available jars will be scanned.

Drools will scan all the jars in the classpath looking for the kmodule.xml file in the META-INF/ directory. When found, this file will load the provided configurations to make them available to use in our applications.

In essence all the KieModules that are found in the classpath of the application will be loaded in the KieContainer.

Loading Rules Using Maven Artifacts (KIE-CI)

In Cases where we don’t want to load all the KieModules that are found in the classpath, will go ahead with this approach.

In this case we don’t add any KieModule dependency in the pom.xml file, instead we add the following dependency.

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-ci</artifactId>
            <version>${kie.version}</version>            
        </dependency>

The above dependency will enable Drools to use the Maven mechanism to resolve the artifacts that are outside the application classpath. Here is how we can create a container in this approach.

KieContainer kContainer = ks.newKieContainer(ks.newReleaseId("com.github.mnadeem", "drools-discount-kjar","0.0.1"));

Notice that in this approach, instead of adding the dependency to our project we are letting the KieContainer resolve an artifact that we are providing based on GAV.

The Drools API allows us to not only use this ReleaseId specific version of the KieModule, but also upgrade it to a newer version, should it be necessary, through the updateToVersion() method. This method will recreate the KieContainer to become an access point to the KieBases and KieSessions of a newer version of the KieModule.

Complete pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.github.mnadeem</groupId>
	<artifactId>boot-drools-kie-ci</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>boot-drools-kie-ci</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<java.version>1.8</java.version>
		<kie.version>7.53.0.Final</kie.version>
	</properties>
	
	<dependencies>
	
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<dependency>
		    <groupId>org.drools</groupId>
		    <artifactId>drools-core</artifactId>
		    <version>${kie.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.kie</groupId>
		    <artifactId>kie-spring</artifactId>
		    <version>${kie.version}</version>
		</dependency>		
		<dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-ci</artifactId>
            <version>${kie.version}</version>
        </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Lets create the following structure, by copying the files from above, note that in this case we have to create Sale.java as well

DroolsConfig.java

package com.github.mnadeem.config;

import org.kie.api.KieServices;
import org.kie.api.builder.Message;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.scanner.KieModuleMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DroolsConfig {

	private static final Logger LOGGER = LoggerFactory.getLogger(DroolsConfig.class);

	@Bean
	public KieContainer kieContainer() {

		KieServices ks = kieServices();
		KieContainer kContainer = ks.newKieContainer(discountsKJar(ks));
		// Let's verify that all the resources are loaded correctly
		Results results = kContainer.verify();
		results.getMessages().stream().forEach((message) -> {
			LOGGER.info(">> Message ( {} ): {}", message.getLevel(), message.getText());
		});
		// If there is an Error we need to stop and correct it
		boolean hasError = results.hasMessages(Message.Level.ERROR);
		LOGGER.info("Any Error : {}", hasError);
		if (hasError) {
			throw new UnsupportedOperationException();
		}
		// Here we make sure that all the KieBases and KieSessions
		// that we are expecting are loaded.
		kContainer.getKieBaseNames().stream().map((kieBase) -> {
			LOGGER.info(">> Loading KieBase: {}", kieBase);
			return kieBase;
		}).forEach((kieBase) -> {
			kContainer.getKieSessionNamesInKieBase(kieBase).stream().forEach((kieSession) -> {
				LOGGER.info("\t >> Containing KieSession: {}", kieSession);
			});
		});

		KieModuleMetaData kieModuleMetaData = KieModuleMetaData.Factory.newKieModuleMetaData(discountsKJar(ks));

		kieModuleMetaData.getPackages().stream().map((pkg) -> {
			LOGGER.info(" >> Package Loaded:  {}", pkg);
			return pkg;
		}).forEach((pkg) -> {
			kieModuleMetaData.getRuleNamesInPackage(pkg).stream().forEach((rule) -> {
				LOGGER.info("\t >> Contain Rule:  {}", rule);
			});
		});

		return kContainer;
	}

	private ReleaseId discountsKJar(KieServices ks) {
		return ks.newReleaseId("com.github.mnadeem", "drools-discount-kjar", "0.0.1-SNAPSHOT");
	}

	private KieServices kieServices() {
		return KieServices.Factory.get();
	}
}

Run the Application

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.4.RELEASE)

2021-05-10 18:23:34.151  INFO 16664 --- [           main] c.g.mnadeem.BootDroolsKieCiApplication   : Starting BootDroolsKieCiApplication on LHTU05CG9234T82 with PID 16664 (C:\Users\reach\eclipse-workspace\2020\drools\boot-drools-kie-ci\target\classes started by mnadeem6 in C:\Users\reach\eclipse-workspace\2020\drools\boot-drools-kie-ci)
2021-05-10 18:23:34.155  INFO 16664 --- [           main] c.g.mnadeem.BootDroolsKieCiApplication   : No active profile set, falling back to default profiles: default
2021-05-10 18:23:40.644  INFO 16664 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-05-10 18:23:40.658  INFO 16664 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-10 18:23:40.659  INFO 16664 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.38]
2021-05-10 18:23:41.947  INFO 16664 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-10 18:23:41.948  INFO 16664 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 7720 ms
2021-05-10 18:23:42.518  WARN 16664 --- [           main] o.a.m.i.embedder.MavenSettings           : Environment variable M2_HOME is not set
2021-05-10 18:23:46.145  INFO 16664 --- [           main] o.d.c.k.b.i.InternalKieModuleProvider    : Creating KieModule for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT
2021-05-10 18:23:46.164  INFO 16664 --- [           main] o.d.m.CanonicalKieModuleProvider         : No executable model found for artifact com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT. Falling back to resources parsing.
2021-05-10 18:23:47.802  INFO 16664 --- [           main] com.github.mnadeem.config.DroolsConfig   : Any Error : false
2021-05-10 18:23:47.805  INFO 16664 --- [           main] com.github.mnadeem.config.DroolsConfig   : >> Loading KieBase: defaultKieBase
2021-05-10 18:23:47.805  INFO 16664 --- [           main] com.github.mnadeem.config.DroolsConfig   : 	 >> Containing KieSession: defaultStatelessKieSession
2021-05-10 18:23:47.805  INFO 16664 --- [           main] com.github.mnadeem.config.DroolsConfig   : 	 >> Containing KieSession: defaultKieSession
2021-05-10 18:23:47.977  INFO 16664 --- [           main] com.github.mnadeem.config.DroolsConfig   :  >> Package Loaded:  com.github.mnadeem.discount.model
2021-05-10 18:23:48.258  INFO 16664 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-10 18:23:48.613  INFO 16664 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-10 18:23:48.634  INFO 16664 --- [           main] c.g.mnadeem.BootDroolsKieCiApplication   : Started BootDroolsKieCiApplication in 14.996 seconds (JVM running for 16.954)

Invoke

curl --location --request POST 'localhost:8080/discount' \
--header 'Content-Type: application/json' \
--data-raw '{
    "quantity": 11,
    "item": "Car"
}'

KieScanner

The KieScanner component in Drools is nothing but a wrapper around a KieContainer that can be configured to automatically detect changes in the resources that the container depends on.

KieServices ks = KieServices.Factory.get();
KieContainer kieContainer = ks.newKieContainer(ks.newReleaseId("group.test","artifact-test", "1.0"));
KieScanner scanner = ks.newKieScanner(kieContainer);

//Manually run a check for new versions
scanner.scanNow();
//Configure the scanner to check for new versions every 10 seconds
scanner.start(10_000);

References

Source Code

Spring Boot Starters for KIE And jBPM Servers

Starters

KIE Starters

jbpm-spring-boot-starter-basic

GAVorg.kie:jbpm-spring-boot-starter-basic
PurposejBPM business process management. Adds jBPM capabilities to your application. It provides the jBPM /RHPAM-embedded runtime and services to run the process execution engine within your application.
LinksMore Info

kie-server-spring-boot-starter

GAV org.kie:kie-server-spring-boot-starter
Purpose Fully featured KIE Server (Drools, jBPM, Optaplanner) : Adds KIE Server capabilities to your application. This allows you to run the KIE Server services and RESTful APIs within your application. This starter provides all the business automation features that Process Automation Manager has to offer. This includes process and case execution (jBPM ), (business) rules and DMN (Decision Model & Notation) execution (Drools ), and business resource optimization (OptaPlanner ).
Links More Info

kie-server-spring-boot-starter-drools

GAV org.kie:kie-server-spring-boot-starter-drools
Purpose Rules and Decisions KIE Server (Drools, DMN) :  Same as kie-server-spring-boot-starter, but has only rules and DMN execution (Drools ) capabilities.
Links More Info

kie-server-spring-boot-starter-jbpm

GAV org.kie:kie-server-spring-boot-starter-jbpm
Purpose Rules and Decisions, Process and Cases KIE Server (Drools, DMN, jBPM, Case mgmt) : Same as kie-server-spring-boot-starter, but has only rules and process and case execution (jBPM) capabilities.
Links More Info

kie-server-spring-boot-starter-optaplanner

GAV org.kie:kie-server-spring-boot-starter-optaplanner
Purpose Planning KIE Server (Optaplanner) : Same as the kie-server-spring-boot-starter, but has only business resource optimization (OptaPlanner ) capabilities.
Links More Info

JBPM KIE Server

https://start.spring.io/

Change the boot-starter version to 2.3.4.RELEASE from 2.4.5.RELEASE

More details

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.kie</groupId>
			<artifactId>kie-server-spring-boot-starter-jbpm</artifactId>
			<version>7.53.0.Final</version>
		</dependency>
		
		<dependency>
		    <groupId>org.apache.tomcat</groupId>
		    <artifactId>tomcat-jdbc</artifactId>
		    <scope>runtime</scope>
		</dependency>

Change the narayana version

<narayana.version>5.6.4.Final</narayana.version>

Complete properties section

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	    <java.version>1.8</java.version>
	    <narayana.version>5.6.4.Final</narayana.version>
	</properties>

Complete pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.github.mnadeem</groupId>
	<artifactId>boot-jbpm-kie-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>boot-jbpm-kie-server</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<narayana.version>5.6.4.Final</narayana.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.kie</groupId>
			<artifactId>kie-server-spring-boot-starter-jbpm</artifactId>
			<version>7.53.0.Final</version>
		</dependency>
		
		<dependency>
		    <groupId>org.apache.tomcat</groupId>
		    <artifactId>tomcat-jdbc</artifactId>
		    <scope>runtime</scope>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>		
	
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

application.properties

server.address=localhost
server.port=8090

# This is must
cxf.path=/rest

# KieServer identifier, location and controllers (Comma separated list of controllers)
kieserver.serverId=boot-kie-server
kieserver.serverName=KIE Server SpringBoot
kieserver.location=http://${server.address}:${server.port}${cxf.path}/server
#kieserver.location=http://localhost:8090/rest/server
#kieserver.controllers=http://localhost:8080/kie-wb/rest/controller

# Kie server extensions
kieserver.drools.enabled=true
kieserver.dmn.enabled=true
kieserver.jbpm.enabled=true
kieserver.jbpmui.enabled=true
kieserver.casemgmt.enabled=true
#kieserver.prometheus.enabled=true
kieserver.scenariosimulation.enabled=true

# Dedicated jBPM properties
jbpm.executor.enabled=false
#jbpm.executor.retries=5
#jbpm.executor.interval=3
#jbpm.executor.threadPoolSize=1
#jbpm.executor.timeUnit=SECONDS

# data source configuration
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.url=jdbc:h2:./target/spring-boot-jbpm
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.type=org.apache.tomcat.jdbc.pool.XADataSource

# hibernate configuration
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

# transaction manager configuration
spring.jta.narayana.transaction-manager-id=1

narayana.dbcp.enabled=true
narayana.dbcp.maxTotal=20

KieSecurityConfig.java

package com.github.mnadeem.kie.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration("kieServerSecurity")
@EnableWebSecurity
public class KieSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .authorizeRequests()
            .antMatchers("/rest/server*").authenticated()
            .and()
        .httpBasic();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        
        auth.inMemoryAuthentication()
            .withUser("kieserver").password(encoder.encode("kieserver1!")).roles("kie-server")
            .and()        
            .withUser("john").password(encoder.encode("john@pwd1")).roles("kie-server", "PM", "HR");        
    }
}

Start The Application

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.4.RELEASE)

2021-05-09 22:02:43.526  INFO 14324 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : Starting BootJbpmKieServerApplication on DESKTOP-9AES3TT with PID 14324 (E:\eWorkspaces\drools\boot-jbpm-kie-server\target\classes started by reach in E:\eWorkspaces\drools\boot-jbpm-kie-server)
2021-05-09 22:02:43.529  INFO 14324 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : No active profile set, falling back to default profiles: default
2021-05-09 22:02:44.877  INFO 14324 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8090 (http)
2021-05-09 22:02:44.887  INFO 14324 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-09 22:02:44.887  INFO 14324 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.38]
2021-05-09 22:02:45.072  INFO 14324 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-09 22:02:45.072  INFO 14324 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1504 ms
2021-05-09 22:02:45.347  WARN 14324 --- [           main] com.arjuna.ats.common                    : ARJUNA048002: Could not find configuration file, URL was: null
2021-05-09 22:02:45.390  INFO 14324 --- [           main] o.d.p.api.TransactionManagerFactory      : Using org.kie.spring.persistence.KieSpringTransactionManagerFactory@20b54cfe
2021-05-09 22:02:45.409  INFO 14324 --- [           main] com.arjuna.ats.jbossatx                  : ARJUNA032010: JBossTS Recovery Service (tag: 92f28891fd5f29d0381da214d4f3a2917f46e301) - JBoss Inc.
2021-05-09 22:02:45.438  INFO 14324 --- [           main] com.arjuna.ats.jbossatx                  : ARJUNA032013: Starting transaction recovery manager
2021-05-09 22:02:45.555  INFO 14324 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: org.jbpm.domain]
2021-05-09 22:02:45.614  INFO 14324 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.21.Final
2021-05-09 22:02:45.751  INFO 14324 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2021-05-09 22:02:46.651  INFO 14324 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2021-05-09 22:02:47.127  INFO 14324 --- [           main] org.hibernate.orm.beans                  : HHH10005002: No explicit CDI BeanManager reference was passed to Hibernate, but CDI is available on the Hibernate ClassLoader.
2021-05-09 22:02:47.473  INFO 14324 --- [d Entry Monitor] com.arjuna.ats.arjuna                    : ARJUNA012332: Failed to establish connection to server
2021-05-09 22:02:47.809  INFO 14324 --- [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform]
2021-05-09 22:02:48.353  WARN 14324 --- [           main] o.h.dialect.function.TemplateRenderer    : HHH000174: Function template anticipated 4 arguments, but 1 arguments encountered
2021-05-09 22:02:48.354  WARN 14324 --- [           main] o.h.dialect.function.TemplateRenderer    : HHH000174: Function template anticipated 4 arguments, but 1 arguments encountered
2021-05-09 22:02:48.405  INFO 14324 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'org.jbpm.domain'
2021-05-09 22:02:48.465  WARN 14324 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-05-09 22:02:48.770  INFO 14324 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4c2b8df7, org.springframework.security.web.context.SecurityContextPersistenceFilter@1bd97254, org.springframework.security.web.header.HeaderWriterFilter@5e91b051, org.springframework.security.web.authentication.logout.LogoutFilter@20e7ea20, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@4f5080ea, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@32b19d03, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@364c4ba9, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@7734ddb8, org.springframework.security.web.session.SessionManagementFilter@46199519, org.springframework.security.web.access.ExceptionTranslationFilter@3d5a6849, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@e00f822]
2021-05-09 22:02:48.860  INFO 14324 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-09 22:02:49.210  INFO 14324 --- [           main] o.k.i.pmml.PMMLImplementationsUtil       : Using NEW implementation
2021-05-09 22:02:49.210  INFO 14324 --- [           main] o.k.i.pmml.PMMLImplementationsUtil       : Using NEW implementation
2021-05-09 22:02:49.338  INFO 14324 --- [           main] com.arjuna.ats.arjuna                    : ARJUNA012170: TransactionStatusManager started on port 50890 and host 127.0.0.1 with service com.arjuna.ats.arjuna.recovery.ActionStatusService
2021-05-09 22:02:49.641  INFO 14324 --- [           main] o.k.s.s.a.KieServerAutoConfiguration     : KieServer (id boot-kie-server (name KIE Server SpringBoot)) started initialization process
2021-05-09 22:02:49.770  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Starting server in 'DEVELOPMENT' mode.
2021-05-09 22:02:49.773  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Selected startup strategy ControllerBasedStartupStrategy - deploys kie containers given by controller ignoring locally defined
2021-05-09 22:02:49.774  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Configured 'KieServerStateFileRepository' server state repository
2021-05-09 22:02:49.800  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Server Default Extension has been successfully registered as server extension
2021-05-09 22:02:49.802  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Drools KIE Server extension has been successfully registered as server extension
2021-05-09 22:02:49.819  INFO 14324 --- [           main] o.k.s.api.marshalling.MarshallerFactory  : Marshaller extensions init
2021-05-09 22:02:49.830  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : jBPM KIE Server extension has been successfully registered as server extension
2021-05-09 22:02:49.832  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Case-Mgmt KIE Server extension has been successfully registered as server extension
2021-05-09 22:02:49.920  INFO 14324 --- [           main] o.k.s.s.j.u.f.r.BootstrapFormRenderer    : Boostrap Form renderer templates loaded successfully.
2021-05-09 22:02:49.924  INFO 14324 --- [           main] o.k.s.s.j.u.f.r.PatternflyFormRenderer   : patternfly Form renderer templates loaded successfully.
2021-05-09 22:02:49.927  INFO 14324 --- [           main] o.k.s.s.j.u.f.r.PatternflyFormRenderer   : workbench Form renderer templates loaded successfully.
2021-05-09 22:02:49.928  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : jBPM-UI KIE Server extension has been successfully registered as server extension
2021-05-09 22:02:49.929  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : DMN KIE Server extension has been successfully registered as server extension
2021-05-09 22:02:49.931  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : Scenario Simulation KIE Server extension has been successfully registered as server extension
2021-05-09 22:02:49.933  INFO 14324 --- [           main] o.k.s.s.impl.policy.PolicyManager        : Registered KeepLatestContainerOnlyPolicy{interval=0 ms} policy under name KeepLatestOnly
2021-05-09 22:02:49.933  INFO 14324 --- [           main] o.k.s.s.impl.policy.PolicyManager        : Policy manager started successfully, activated policies are []
2021-05-09 22:02:49.936  INFO 14324 --- [           main] o.k.s.services.impl.ContainerManager     : About to install containers on kie server 
	KieServer{id='boot-kie-server'name='KIE Server SpringBoot'version='7.53.0.Final'location='http://localhost:8090/rest/server'}:
	
2021-05-09 22:02:49.941  INFO 14324 --- [           main] o.k.server.services.impl.KieServerImpl   : KieServer boot-kie-server is ready to receive requests
2021-05-09 22:02:49.971  INFO 14324 --- [           main] o.k.s.s.a.KieServerAutoConfiguration     : KieServer (id boot-kie-server) started successfully
2021-05-09 22:02:50.145  INFO 14324 --- [           main] org.apache.cxf.endpoint.ServerImpl       : Setting the server's publish address to be /
2021-05-09 22:02:50.253  INFO 14324 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8090 (http) with context path ''
2021-05-09 22:02:50.262  INFO 14324 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : Started BootJbpmKieServerApplication in 7.039 seconds (JVM running for 7.575)

Access KieServer

Using Postman


curl --location --request GET 'http://localhost:8090/rest/server/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \

Create Container

Create KieModule

Add the properties section in pom.xml

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
</properties>

Create META-INF folder

Lets further create the following files

Sale.java

package com.github.mnadeem.discount.model;
 
public class Sale {
     
    private int quantity;
    private String item;
    private int discount;
  
    public int getQuantity() {
        return quantity;
    }
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
    public String getItem() {
        return item;
    }
    public void setItem(String item) {
        this.item = item;
    }
    public int getDiscount() {
        return discount;
    }
    public void setDiscount(int discount) {
        this.discount = discount;
    }   
}

kmodule.xml

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://jboss.org/kie/6.0.0/kmodule">
 
</kmodule>

discount.drl

package rules;
  
import com.github.mnadeem.discount.model.Sale;
  
rule "DiscountForCarSale"
    when
        thisSale : Sale (quantity >= 5 , item == "Car");
    then
        thisSale.setDiscount(10);
end;
  
rule "DiscountForBikeSale"
    when
        thisSale : Sale (quantity >= 10 , item == "Bike");
    then
        thisSale.setDiscount(15);
end;

This would create drools-discount-kjar-0.0.1-SNAPSHOT.jar

Creating Container Using Rest

Refer this for more details on KIE Server rest api

Note: com.github.mnadeem:drools-discount-kjar Should exist in maven repo

curl --location --request PUT 'http://localhost:8090/rest/server/containers/testFirstContainer' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \
--header 'Cookie: JSESSIONID=1699404DEF6AE8DF1F102733FD463AE2' \
--data-raw '{
  "config-items": [
    {
      "itemName": "RuntimeStrategy",
      "itemValue": "SINGLETON",
      "itemType": "java.lang.String"
    },
    {
      "itemName": "MergeMode",
      "itemValue": "MERGE_COLLECTIONS",
      "itemType": "java.lang.String"
    },
    {
      "itemName": "KBase",
      "itemValue": "",
      "itemType": "java.lang.String"
    },
    {
      "itemName": "KSession",
      "itemValue": "",
      "itemType": "java.lang.String"
    }
  ],
  "release-id": {
    "group-id": "com.github.mnadeem",
    "artifact-id": "drools-discount-kjar",
    "version": "0.0.1-SNAPSHOT"
  },
  "scanner": {
    "poll-interval": "5000",
    "status": "STARTED"
  }
}'

Creating Container Using Java

		<dependency>
            <groupId>org.kie.server</groupId>
            <artifactId>kie-server-client</artifactId>
            <version>${kie.version}</version>
        </dependency>

import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.api.model.KieContainerResource;
import org.kie.server.api.model.KieContainerStatus;
import org.kie.server.api.model.ReleaseId;
import org.kie.server.api.model.ServiceResponse;
import org.kie.server.client.KieServicesClient;
import org.kie.server.client.KieServicesConfiguration;
import org.kie.server.client.KieServicesFactory;


	private static final String CONTAINER_ID = "my-deploy";
	private static final String USER = "kieserver";
	private static final String PASSWORD = "kieserver1!";
	private static final String URL = "http://localhost:8090/rest/server";

		KieServicesConfiguration config = KieServicesFactory.newRestConfiguration(URL, USER, PASSWORD, 60000);
		config.setMarshallingFormat(MarshallingFormat.JSON);

		KieServicesClient client = KieServicesFactory.newKieServicesClient(config);
		KieContainerResource kContainer = new KieContainerResource();
		kContainer.setContainerId(CONTAINER_ID);
		kContainer.setReleaseId(new ReleaseId("com.github.mnadeem", "drools-discount-kjar", "0.0.1-SNAPSHOT"));

		ServiceResponse<KieContainerResource> resp = client.createContainer(CONTAINER_ID, kContainer);
		KieContainerStatus status = resp.getResult().getStatus();
		if (!KieContainerStatus.STARTED.equals(status)) {
			throw new IllegalStateException();
		}

2021-05-11 01:08:20.956  INFO 2648 --- [0.1-8090-exec-4] o.k.s.s.jbpm.JbpmKieServerExtension      : Container my-deploy does not include processes, jBPM KIE Server extension skipped
2021-05-11 01:08:20.956  INFO 2648 --- [0.1-8090-exec-4] o.k.server.services.impl.KieServerImpl   : Container my-deploy (for release id com.github.mnadeem:drools-discount-kjar:0.0.1-SNAPSHOT) successfully started
2021-05-11 01:08:20.958  WARN 2648 --- [0.1-8090-exec-4] o.k.s.s.i.c.DefaultRestControllerImpl    : No controllers found to update to new status org.kie.server.api.model.KieServerStateInfo@6e6283d9

Other Rest APIs

Get All Containers

curl --location --request GET 'http://localhost:8090/rest/server/containers' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \
--header 'Cookie: JSESSIONID=4662D6ED2610331EE5718976F233090F'

Get Specific Container

curl --location --request GET 'http://localhost:8090/rest/server/containers/my-deploy' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \
--header 'Cookie: JSESSIONID=4662D6ED2610331EE5718976F233090F'

Execute A Rule In A Container

curl --location --request POST 'http://localhost:8090/rest/server/containers/instances/my-deploy' \
--header 'Content-Type: application/json' \
--header 'X-KIE-ContentType: JSON' \
--header 'Authorization: Basic a2llc2VydmVyOmtpZXNlcnZlcjEh' \
--header 'Cookie: JSESSIONID=4662D6ED2610331EE5718976F233090F' \
--data-raw '{
  "lookup" : null,
  "commands" : [ {
    "insert" : {
      "object" : {"com.github.mnadeem.discount.model.Sale":{
  "quantity" : 100,
  "item" : "Car",
  "discount" : 0
}},
      "out-identifier" : "Sale",
      "return-object" : true,
      "entry-point" : "DEFAULT",
      "disconnected" : false
    }
  }, {
    "fire-all-rules" : {
      "max" : -1,
      "out-identifier" : null
    }
  } ]
}'

Refer this for more details

Controller Integration

If controller is up and running, add the following in application.properties

kieserver.controllers=http://localhost:8080/business-central/rest/controller

and add the following vm argument

-Dorg.kie.server.controller.user=testuser -Dorg.kie.server.controller.pwd=test

Logs after controller integration

2021-05-13 04:34:37.167  INFO 7132 --- [           main] o.k.s.s.a.KieServerAutoConfiguration     : KieServer (id boot-kie-server (name KIE Server SpringBoot)) started initialization process
2021-05-13 04:34:37.350  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Starting server in 'DEVELOPMENT' mode.
2021-05-13 04:34:37.353  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Selected startup strategy ControllerBasedStartupStrategy - deploys kie containers given by controller ignoring locally defined
2021-05-13 04:34:37.354  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Configured 'KieServerStateFileRepository' server state repository
2021-05-13 04:34:37.362  INFO 7132 --- [           main] o.k.s.s.impl.storage.KieServerState      : Added default controller located at http://localhost:8080/business-central/rest/controller
2021-05-13 04:34:37.373  INFO 7132 --- [           main] o.k.s.s.impl.storage.KieServerState      : Added default controller located at http://localhost:8080/business-central/rest/controller
2021-05-13 04:34:37.380  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Server Default Extension has been successfully registered as server extension
2021-05-13 04:34:37.381  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Drools KIE Server extension has been successfully registered as server extension
2021-05-13 04:34:37.398  INFO 7132 --- [           main] o.k.s.api.marshalling.MarshallerFactory  : Marshaller extensions init
2021-05-13 04:34:37.409  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : jBPM KIE Server extension has been successfully registered as server extension
2021-05-13 04:34:37.410  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Case-Mgmt KIE Server extension has been successfully registered as server extension
2021-05-13 04:34:37.517  INFO 7132 --- [           main] o.k.s.s.j.u.f.r.BootstrapFormRenderer    : Boostrap Form renderer templates loaded successfully.
2021-05-13 04:34:37.521  INFO 7132 --- [           main] o.k.s.s.j.u.f.r.PatternflyFormRenderer   : patternfly Form renderer templates loaded successfully.
2021-05-13 04:34:37.524  INFO 7132 --- [           main] o.k.s.s.j.u.f.r.PatternflyFormRenderer   : workbench Form renderer templates loaded successfully.
2021-05-13 04:34:37.525  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : jBPM-UI KIE Server extension has been successfully registered as server extension
2021-05-13 04:34:37.527  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : DMN KIE Server extension has been successfully registered as server extension
2021-05-13 04:34:37.529  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : Scenario Simulation KIE Server extension has been successfully registered as server extension
2021-05-13 04:34:37.532  INFO 7132 --- [           main] o.k.s.s.impl.policy.PolicyManager        : Registered KeepLatestContainerOnlyPolicy{interval=0 ms} policy under name KeepLatestOnly
2021-05-13 04:34:37.532  INFO 7132 --- [           main] o.k.s.s.impl.policy.PolicyManager        : Policy manager started successfully, activated policies are []
2021-05-13 04:34:37.535  WARN 7132 --- [           main] o.kie.server.common.KeyStoreHelperUtil   : Unable to load key store. Using password from configuration
2021-05-13 04:34:38.409  INFO 7132 --- [           main] o.k.s.services.impl.ContainerManager     : About to install containers on kie server 
	KieServer{id='boot-kie-server'name='KIE Server SpringBoot'version='7.53.0.Final'location='http://localhost:8090/rest/server'}:
	
2021-05-13 04:34:38.416  INFO 7132 --- [           main] o.k.server.services.impl.KieServerImpl   : KieServer boot-kie-server is ready to receive requests
2021-05-13 04:34:38.456  INFO 7132 --- [           main] o.k.s.s.a.KieServerAutoConfiguration     : KieServer (id boot-kie-server) started successfully
2021-05-13 04:34:38.671  INFO 7132 --- [           main] org.apache.cxf.endpoint.ServerImpl       : Setting the server's publish address to be /
2021-05-13 04:34:38.835  INFO 7132 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8090 (http) with context path ''
2021-05-13 04:34:38.844  INFO 7132 --- [           main] c.g.m.kie.BootJbpmKieServerApplication   : Started BootJbpmKieServerApplication in 8.409 seconds (JVM running for 8.929)
2021-05-13 04:34:39.160  INFO 7132 --- [0.1-8090-exec-1] o.k.s.a.m.xstream.XStreamMarshaller      : XStreamMarshallerExtension implementation found: org.kie.server.services.jbpm.xstream.HibernateXStreamMarshallerExtension
2021-05-13 04:34:39.251  INFO 7132 --- [0.1-8090-exec-1] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmExecutionErrorList updated in db storage
2021-05-13 04:34:39.252  INFO 7132 --- [0.1-8090-exec-1] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmExecutionErrorList query successfully
2021-05-13 04:34:39.349  INFO 7132 --- [0.1-8090-exec-2] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmHumanTasks updated in db storage
2021-05-13 04:34:39.350  INFO 7132 --- [0.1-8090-exec-2] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmHumanTasks query successfully
2021-05-13 04:34:39.420  INFO 7132 --- [0.1-8090-exec-3] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmHumanTasksWithAdmin updated in db storage
2021-05-13 04:34:39.422  INFO 7132 --- [0.1-8090-exec-3] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmHumanTasksWithAdmin query successfully
2021-05-13 04:34:39.496  INFO 7132 --- [0.1-8090-exec-4] o.j.k.s.i.q.p.PersistDataSetListener     : Data set processesMonitoring updated in db storage
2021-05-13 04:34:39.496  INFO 7132 --- [0.1-8090-exec-4] o.j.k.s.impl.query.QueryServiceImpl      : Registered processesMonitoring query successfully
2021-05-13 04:34:39.567  INFO 7132 --- [0.1-8090-exec-5] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmRequestList updated in db storage
2021-05-13 04:34:39.567  INFO 7132 --- [0.1-8090-exec-5] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmRequestList query successfully
2021-05-13 04:34:39.636  INFO 7132 --- [0.1-8090-exec-6] o.j.k.s.i.q.p.PersistDataSetListener     : Data set tasksMonitoring updated in db storage
2021-05-13 04:34:39.638  INFO 7132 --- [0.1-8090-exec-6] o.j.k.s.impl.query.QueryServiceImpl      : Registered tasksMonitoring query successfully
2021-05-13 04:34:39.708  INFO 7132 --- [0.1-8090-exec-7] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmHumanTasksWithUser updated in db storage
2021-05-13 04:34:39.708  INFO 7132 --- [0.1-8090-exec-7] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmHumanTasksWithUser query successfully
2021-05-13 04:34:39.780  INFO 7132 --- [0.1-8090-exec-8] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmProcessInstancesWithVariables updated in db storage
2021-05-13 04:34:39.780  INFO 7132 --- [0.1-8090-exec-8] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmProcessInstancesWithVariables query successfully
2021-05-13 04:34:39.849  INFO 7132 --- [0.1-8090-exec-9] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmProcessInstances updated in db storage
2021-05-13 04:34:39.850  INFO 7132 --- [0.1-8090-exec-9] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmProcessInstances query successfully
2021-05-13 04:34:39.919  INFO 7132 --- [.1-8090-exec-10] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmHumanTasksWithVariables updated in db storage
2021-05-13 04:34:39.919  INFO 7132 --- [.1-8090-exec-10] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmHumanTasksWithVariables query successfully
2021-05-13 04:34:39.988  INFO 7132 --- [0.1-8090-exec-1] o.j.k.s.i.q.p.PersistDataSetListener     : Data set jbpmProcessInstanceLogs updated in db storage
2021-05-13 04:34:39.988  INFO 7132 --- [0.1-8090-exec-1] o.j.k.s.impl.query.QueryServiceImpl      : Registered jbpmProcessInstanceLogs query successfully

References

Also See

Source Code

Getting Started With Drools In Spring Boot Project

Lets embed rule engine execution within spring boot application

Create Spring Boot Project

https://start.spring.io/

Add the following pom dependencies

        <dependency>
		    <groupId>org.drools</groupId>
		    <artifactId>drools-core</artifactId>
		    <version>${kie.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.kie</groupId>
		    <artifactId>kie-spring</artifactId>
		    <version>${kie.version}</version>
		</dependency>

kie.version == 7.53.0.Final

DependencyNotes
org.drools:drools-coreDrools rule engine implementation
org.kie:kie-springContains, org.kie:kie-api, org.drools:drools-compiler, jbpm and spring related dependencies
org.kie:kie-api Contains all the public interfaces exposed
by the KIE Platform, which is composed by Drools, jBPM, and OptaPlanner
org.drools:drools-compilerContains the algorithm to translate the rules written in different resources
(text files, spreadsheets, your own types, and so on) to executable rules.
This artifact is required only because we are compiling our rules in the project.
It is possible to separate the rules compilation from the rules execution to remove this dependency from our project; however, for the sake of simplicity, we are going to compile our
rules in the same project.

Eclipse Plugin

This would be helpful to edit drl files

Rule Implementation

Lets create the following structure

DroolsConfig

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 DroolsConfig {

	private static final String RULES_PATH = "rules/";

	@Bean
	public KieFileSystem kieFileSystem() throws IOException {
		KieFileSystem kieFileSystem = kieServices().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(KieFileSystem kieFileSystem) throws IOException {
		final KieRepository kieRepository = kieRepository();
		KieBuilder kieBuilder = kieServices().newKieBuilder(kieFileSystem);
		kieBuilder.buildAll();
		return kieServices().newKieContainer(kieRepository.getDefaultReleaseId());
	}
 
	private KieRepository kieRepository() {
		final KieRepository kieRepository = kieServices().getRepository();
		kieRepository.addKieModule(new KieModule() {
			public ReleaseId getReleaseId() {
				return kieRepository.getDefaultReleaseId();
			}
		});
		return kieRepository;
	}

	private KieServices kieServices() {
		return KieServices.Factory.get();
	}
}

Sale

public class Sale {
	
	private int quantity;
	private String item;
	private int discount;

	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
	public String getItem() {
		return item;
	}
	public void setItem(String item) {
		this.item = item;
	}
	public int getDiscount() {
		return discount;
	}
	public void setDiscount(int discount) {
		this.discount = discount;
	}	
}

discount.drl

package rules;

import com.github.mnadeem.discount.model.Sale;

rule "DiscountForCarSale"
	when
		thisSale : Sale (quantity >= 5 , item == "Car");
	then
		thisSale.setDiscount(10);
end;

rule "DiscountForBikeSale"
	when
		thisSale : Sale (quantity >= 10 , item == "Bike");
	then
		thisSale.setDiscount(15);
end;

DiscountService

import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.stereotype.Service;

import com.github.mnadeem.discount.model.Sale;

@Service
public class DiscountService {

	private final KieContainer kieContainer;

	public DiscountService(KieContainer kieContainer) {
		this.kieContainer = kieContainer;
	}

	public void applyDiscount(Sale sale) {
		KieSession kieSession = kieContainer.newKieSession();
		kieSession.insert(sale);
		kieSession.fireAllRules();
		kieSession.dispose();
	}
}

DiscountController

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.github.mnadeem.discount.model.Sale;

@RestController
public class DiscountController {

	private DiscountService discountService;

	public DiscountController(DiscountService service) {
		this.discountService = service;
	}

	@PostMapping("/discount")
	private Sale getDiscountPercent(@RequestBody Sale sale) {		
		this.discountService.applyDiscount(sale);
	    return sale;
	}
}

Start the Application

2021-05-09 00:19:41.127  INFO 624 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-09 00:19:41.288  INFO 624 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-09 00:19:41.298  INFO 624 --- [           main] c.g.m.BootDroolsEmbeddedApplication      : Started BootDroolsEmbeddedApplication in 2.14 seconds (JVM running for 2.486)
2021-05-09 00:19:42.753  INFO 624 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-05-09 00:19:42.753  INFO 624 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-05-09 00:19:42.754  INFO 624 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2021-05-09 00:19:42.816  INFO 624 --- [nio-8080-exec-1] o.d.c.kie.builder.impl.KieContainerImpl  : Start creation of KieBase: defaultKieBase
2021-05-09 00:19:42.870  INFO 624 --- [nio-8080-exec-1] o.d.c.kie.builder.impl.KieContainerImpl  : End creation of KieBase: defaultKieBase

Execute Rule

localhost:8080/discount

{
    "quantity": 11,
    "item": "Car"
}

Junit Test Cases

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.github.mnadeem.discount.DiscountService;
import com.github.mnadeem.discount.model.Sale;

@SpringBootTest
class BootDroolsEmbeddedApplicationTests {
	
	@Autowired
	private DiscountService discountService;

	@Test
	void discountOnCarWithQuantityMoreThan5ShouldBe10() {
		Sale sale = new Sale();
		sale.setItem("Car");
		sale.setQuantity(11);
		discountService.applyDiscount(sale);
		
		assertEquals(10, sale.getDiscount());
	}
	
	@Test
	void discountOnBikeWithQuantityMoreThan10ShouldBe15() {
		Sale sale = new Sale();
		sale.setItem("Bike");
		sale.setQuantity(11);
		discountService.applyDiscount(sale);
		
		assertEquals(15, sale.getDiscount());
	}
}

KIE Components

Kie = Knowledge is Everything

ComponentNotes
KieServices KieServices class that gives us access to all these other concepts by providing a registry of services where we can find helpers for different purposes. Using the KieServices, we can access a number of factories, services, and utility methods used along with Rule Engine instances.

KieServices ks = KieServices.Factory.get();
KieContainerdefines the scope of the rules that will be used to create new instances of the Rule Engine. A KieContainer can host a KieModule and its dependencies.

Internally, the KieContainer has references to all the business assets (rules, processes,
spreadsheets, PMML documents, and so on) that will be loaded when we create new
Rule Engine instances.
KieModule In Drools 6, everything is created around KieModules. Each KieModule contains
business assets (business rules, business processes, decision tables, and so on) related
to a certain area or domain.

A KieModule is a standard Java-Maven project containing the rules, business process
and other assets among its resources. A special file called kmodule.xml (in the METAINF/
directory) that defines the internal configuration about how to group and
consume these particular assets must also be present in it.
KieBase A KieBase represents a compiled version of a set of assets
KieSession A KieSession represents an instance of the rule engine containing the rules in the KieBase. For this reason, it makes sense to have multiple sessions defined with different configurations for the same KieBase.

KieBase and KieSession, we can define the granularity of how the rules will need to be loaded.

KIE Server

The KIE Server is a standalone execution server for rules.

KIE Server is a modular, standalone server component that can be used to instantiate and execute rules and processes. It exposes this functionality via REST, JMS and Java interfaces to client application. It also provides seamless integration with the Business Central.

The main purpose of the Kie Server is to be a runtime environment for Kie components.

Each instance of the Kie Server can create and use many Kie Containers, and its functionality can be extended through the use of something called Kie Server Extensions.

Also, the Kie Server allows us to provide Kie Server Controllers. These are endpoints which will expose Kie Server functionalities. In a sense, they will be the front-end of our Kie Server.

Refer this on deploying Kie Server

KIE Workbench (Business Central)

KIE Workbench, a Drools based BRMS.

A platforms that allow business experts to access rule writing in a more user-friendly way. These platforms are a composition of user-friendly editors, with versioning and publishing capabilities, called Business Rule Management Systems (BRMS)

The Drools workbench (Business Central) is built with the UberFire framework and uses the Guvnor plugin. Drools provides an additional rich set of plugins for rule authoring metaphors.


Kie Workbench is a web environment where we can create and test all sorts of Kie assets, such as rules, processes, and data models. It is a very useful tool to include business people with little technical knowledge of the specifics of implementation into the development cycle, because it provides a user-friendly environment for rule writing.

KIE Projects

Other Options

KieModule In Classpath

External Repository

Drools getting our rules from an external repository

Alternatively, we can directly build our Kie Container objects based on a specific version of our code. If done this way, we can use a KieScanner to let our runtime know it should monitor the repository for possible future changes, so that the runtime can change versions without even having to restart:

KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.newKieContainer(ks.newReleaseId("com.github.mnadeem","discount-app", "0.1-SNAPSHOT"));

KieScanner kScanner = ks.newKieScanner(kContainer);
kScanner.start(10_000);
KieSession kSession = kContainer.newKieSession();

Refer this for more details

Drools As A Service

Refer this for the implementation

Refer this for implementation

Miscellaneous

Change Database

Refer this for more details

Integrate With OAuth for SSO

TODO

LDAP Integration

See this for more details

Also See

Source Code