Using Global Variables in Drools Decision Tables

Drools Global Variables

Using Global Variables in Drools decision tables opens many options for a programmer to handle rule execution data inside rules, and also to exchange that data with wrapper program which is executing rules. In this post, we’d go through a simple example of global variable usage in Drools decision table step by step. This can be extended to perform complex rules operations using global variables in Drools decision tables. Towards end, there are couple of troubleshooting scenarios explained. We continue to use Drools 6.4, Eclipse Mars, Eclipse plugin for Drools and Java 1.8.

I am assuming, you have already gone through previous two posts – beginners Drools tutorial and Drools decision tables tutorial. These two tutorials will help to understand basic rule execution, and guide how to set up Drools decision table project?

What is a Global Variable in Drools Decision Table?

If we look at the structure of Drools decision table, there are two primary sections, one is Rule Set area and other is actual rules section. Now rule set area has got attributes that are used or apply across rules below, i.e. these can be called as meta data for rules. RuleSet, Sequential, import, variables, functions and queries are the attributes. Name itself tells much about each attribute. We are going to look at variables attribute.

Drools Global Variable Specification

Variables – optional, can be repeated

This is the specification of variable attribute. It is optional i.e. if rule set does not demand any global variable, one can continue without it. If there is requirement of more than one global variable in rules authoring, one can use more than one variable.

Drools Global Variable Syntax

Variables <variable type> <variable name>

This is syntax to declare a global variable. Here the variable type can be a generic type from dialect language or a type from import list. In example below it is of type java.util.Map

Drools Global Variables

How to Use Global Variable in Drools Decision Tables?

If we take a closer look at this example above, we haven’t declared this variable in RuleSet area, instead we have kept it below rules. This is allowed in decision tables. Wherever we want to use this variable, we can use it. In this example we are using it to consolidate the ACTION results. Similarly, this can be used in CONDITION also.

Decision Table Global Variables and Java Program

Below is the Java code to run above decision table example. Only modified code is added below, remaining set up of Drools decision table example remains same as previous post.

CustomerRuleObject.java

package net.deepakgaikwad.drools;

public class CustomerRuleObject {

	private String firstName;

	private String lastName;

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
}

RunRule.java

package net.deepakgaikwad.drools;

import java.util.HashMap;
import java.util.Map;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class RunRule {

	public static void main(String[] args) {

		try {
			KieServices ks = KieServices.Factory.get();
			KieContainer kContainer = ks.getKieClasspathContainer();
			KieSession kSession = kContainer.newKieSession("ksession-dtables");

			RunRule runRule = new RunRule();

			kSession.insert(runRule.createCustomer());
			Map<String, String> abc = new HashMap<String, String>();
			kSession.setGlobal("result", abc);
			kSession.fireAllRules();

			System.out.println(abc);

		} catch (Exception ex) {
			// ignore this crude stuff
			ex.printStackTrace();
		}
	}

	private CustomerRuleObject createCustomer() {
		CustomerRuleObject customerRule = new CustomerRuleObject();

		customerRule.setFirstName("Deepak");
		customerRule.setLastName("Gaikwad");
		return customerRule;
	}

}

In above RunRule class main method, we are doing following things –

  • Initializing global variable declared in rules excel, it can be seen that the variable here is strongly typed as opposed to the declaration in decision table
  • Setting it in KieSession with same name as declared in rules excel, “result”
  • Firing all the rules
  • Printing results

Below is the output of this program, where last line is important.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
{Rule_II=b,d, Rule_I=a,b,c}

If we do not initialize the global variable in Java program the way we did for above, it results in null pointer, something similar to following exception.

Exception executing consequence for rule "CustomerRule_11" in net.deepakgaikwad.drools: java.lang.NullPointerException
	at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
	at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1100)
	at org.drools.core.phreak.RuleExecutor.fire(RuleExecutor.java:121)
	at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:74)
	at org.drools.core.common.DefaultAgenda.fireNextItem(DefaultAgenda.java:1007)
	at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1350)
	at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1288)
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1306)
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1297)
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1278)
	at net.deepakgaikwad.drools.RunRule.main(RunRule.java:24)
Caused by: java.lang.NullPointerException
	at net.deepakgaikwad.drools.Rule_CustomerRule_1190695306.defaultConsequence(Rule_CustomerRule_1190695306.java:7)
	at net.deepakgaikwad.drools.Rule_CustomerRule_1190695306DefaultConsequenceInvokerGenerated.evaluate(Unknown Source)
	at net.deepakgaikwad.drools.Rule_CustomerRule_1190695306DefaultConsequenceInvoker.evaluate(Unknown Source)
	at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1089)
	... 9 more

If we have a global variable set in Java program which is not declared in decision table excel, then Drools execution throws following exception.

SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
java.lang.RuntimeException: Unexpected global [result1]
	at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1162)
	at net.deepakgaikwad.drools.RunRule.main(RunRule.java:23)

To summarize, global variables can be used to implement complex rules and to exchange data between decision tables and client program.

Be the first to comment

Leave a Reply

Your email address will not be published.


*