I'm trying the following tutorial https://www.mastertheboss.com/bpm/drools/jboss-drools-tutorial/?expand_article=1 to help familiarise myself with drools and am encountering the following error.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.kie.api.runtime.KieSession.insert(Object)" because "ksession" is null
at com.sample.DroolsShop.execute(DroolsShop.java:22)
at com.sample.DroolsShop.main(DroolsShop.java:13)
(I am using Eclipse and the droolsjbpm-tools-distribution-7.41.0.Final plugin)
Having done some research, I'm aware that common reasons for this error include, missing a pom.properties file, missing the kmodule file or failing to name the kbase rule. However, as far as I'm aware this is not the case for me.
Here is the code:
DroolsShop.java:
package com.sample;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
public class DroolsShop {
public static final void main(String[] args) {
KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
System.out.println(kc.verify().getMessages().toString());
execute( kc );
}
public static void execute( KieContainer kc ) {
KieSession ksession = kc.newKieSession("ksession-rules");
//KieSession ksession = kc.newKieSession();
Customer mark = new Customer( "mark",
0 );
ksession.insert( mark );
Product shoes = new Product( "shoes",
60 );
ksession.insert( shoes );
Product hat = new Product( "hat",
60 );
ksession.insert( hat );
ksession.insert( new Purchase( mark,
shoes ) );
FactHandle hatPurchaseHandle = ksession.insert( new Purchase( mark,
hat ) );
ksession.fireAllRules();
ksession.delete( hatPurchaseHandle );
System.out.println( "Customer mark has returned the hat" );
ksession.fireAllRules();
}
public static class Customer {
private String name;
private int discount;
public Customer(String name,
int discount) {
this.name = name;
this.discount = discount;
}
public String getName() {
return name;
}
public int getDiscount() {
return discount;
}
public void setDiscount(int discount) {
this.discount = discount;
}
}
public static class Discount {
private Customer customer;
private int amount;
public Discount(Customer customer,
int amount) {
this.customer = customer;
this.amount = amount;
}
public Customer getCustomer() {
return customer;
}
public int getAmount() {
return amount;
}
}
public static class Product {
private String name;
private float price;
public Product(String name,
float price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
}
public static class Purchase {
private Customer customer;
private Product product;
public Purchase(Customer customer,
Product product) {
this.customer = customer;
this.product = product;
}
public Customer getCustomer() {
return customer;
}
public Product getProduct() {
return product;
}
}
}
Rule.drl:
package com.sample.rules
dialect "mvel"
import com.sample.DroolsShop.Customer
import com.sample.DroolsShop.Product
import com.sample.DroolsShop.Purchase
import com.sample.DroolsShop.Discount
rule "Purchase notification"
salience 10
when
$c : Customer()
$p : Purchase( customer == $c )
then
System.out.println( "Customer " + $c.name + " just purchased " + $p.product.name );
end
rule "Discount removed notification"
when
$c : Customer()
not Discount( customer == $c )
then
$c.discount = 0;
System.out.println( "Customer " + $c.name + " now has a discount of " + $c.discount );
end
rule "Discount awarded notification"
when
$c : Customer()
$d : Discount( customer == $c )
then
System.out.println( "Customer " + $c.name + " now has a discount of " + $d.amount );
end
rule "Apply 10% discount if total purchases is over 100"
no-loop true
dialect "java"
when
$c : Customer()
$i : Double(doubleValue > 100) from accumulate (
Purchase( customer == $c, $price : product.price ),
sum( $price )
)
then
$c.setDiscount( 10 );
insertLogical( new Discount( $c, 10 ) );
System.out.println( "Customer " + $c.getName() + " now has a shopping total of " + $i );
end
kmodule.xml:
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules" packages="com.sample.rules">
<ksession name="ksession-rules"/>
</kbase>
<kbase name="dtables" packages="com.sample.dtables">
<ksession name="ksession-dtables"/>
</kbase>
<kbase name="process" packages="com.sample.process">
<ksession name="ksession-process"/>
</kbase>
</kmodule>
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>DemoDrools</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>Drools :: Sample Maven Project</name>
<description>A sample Drools Maven project</description>
<properties>
<runtime.version>7.0.0.Final</runtime.version>
<drools.version>8.44.0.Final</drools.version>
</properties>
<repositories>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-io</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-xml-support</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${drools.version}</version>
</dependency>
</dependencies>
</project>
Project Structure: DroolsShop Eclipse project structure
Any help in diagnosing what could be the problem here would be much appreciated. Thank you.
Here, your KieSession "kiesession-rules" is a a property of the KieBase "rules", not of the container.
public static void execute( KieContainer kc ) {
KieBase kBase = kc.getKieBase("rules");
KieSession ksession = kBase.newKieSession("ksession-rules");
// ...