Open Your Business Rules!                     
Rules-based Operational Decision Services

External Rules Coming from Java

Rule Project "ExternalRulesFromJava"

Step 1. Setting Up Rule Templates

Step 2. Defining Rule Tables in Java

Step 3. Executing External Rules from a Java Program

The OpenRulesEngine can be created with additional parameter of the predefined type ExternalRules allowing to bring into consideration rule tables defined as Java objects. The project "ExternalRulesFromDJava" demonstrates different ways of defining external rules in Java. For simplicity this project intends to produce simple greetings like "Good Morning" based on the current time of the day.

Step 1. Setting Up Rule Templates       top

The business logic for producing greetings is presented in the Excel file HelloTemplates.xls.  The template

Rules void defineGreeting(Request request, Response response)
C1 A1
min <= request.hour && request.hour <= max

response.result = greeting; 

int min int max String greeting
Hour From Hour To Set Greeting
    How are you (default greeting)

specifies how to define different greetings (Good Morning, Good Afternoon, etc.) based on the hour of the day. The current hour is expected to be an attribute if the object request that comes as the first parameter. The resulting greeting is expected to be saved inside the second parameter Response. If the "hour" belongs to the interval [min;max] then a concrete rule that defines this interval will be satisfied. If no rules are satisfied, this multi-hit table will use the default greeting "How are you (default greeting)". 

The second template

Rules void defineGreetingHorizontal(Request request, Response response)
C1 min <= request.hour && request.hour <= max int min Hour From  
int max Hour To  
A1

response.result = greeting; 

String greeting Set Greeting How are you (horizontal default greeting)

demonstrates how external rules deal with horizontal vs vertical rule tables.

Step 2. Defining Rule Tables in Java     top

All Java classes are typical for basic rule projects. There is a special constructor

OpenRulesEngine(String excelFileName, ExternalRules rules)

that has an additional parameter of the predefined Java type ExternalRules. You may create an object of this type like

ExternalRules externalRules = new ExternalRules();

and then add different rule tables using the method:

addRuleTable(String ruleTableName,
                  String ruleTemplateName,
                  Object[][] ruleGrid);

The complete API is described at OpenRules API.

In this project the main Java class RunExternalRules shows different ways for adding rule tables to the external rules. Here is the first rule table:

externalRules.addRuleTable(
	"ExternalSummerGreeting", //table name 
	"defineGreeting", 	  //template name
	new String[][] {	  //rules
		new String[] {"0","11","Good Morning Summer"},
		new String[] {"12","17","Good Afternoon Summer"},
		new String[] {"18","21","Good Evening Summer"},
		new String[] {"22","24","Good Night Summer"}
	}
);

The first parameter specifies the rule table name. The second parameter specifies the template based on which this table will be created. The third parameter defines a grid that is two-dimensional array Object[][] containing actual rules. This grid corresponds to the template "defineGreeting" - see above. The first rule in the grid states that IF Hour From is "0" AND Hour To is "11" THEN Set Greeting as "Good Morning Summer", etc.

The second rule table

externalRules.addRuleTable(
	"ExternalWinterGreeting", //table name 
	"defineGreeting", 	  //template name
	new String[][] {	  //rules
		new String[] {"0","12","Good Morning Winter"},
		new String[] {"13","16","Good Afternoon Winter"},
		new String[] {"17","22","Good Evening Winter"},
		new String[] {"23","24","Good Night Winter"}
	}
);

is very similar to the first one but defines greeting rules for a winter season.

The third rule table

externalRules.addRuleTable(
	"ExternalGreetingHorizontal", //table name 
	"defineGreetingHorizontal",   //template name
	new String[][] {	      //rules
		new String[] {"0","11","Good Morning"},   
		new String[] {"12","16","Good Afternoon"},
		new String[] {"17","22","Good Evening"},
		new String[] {"23","24","Good Night"}
	}
);

shows that you may use a horizontal template "ExternalGreetingHorizontal" and still use the same vertical structure of your rules.

The fourth rule table

externalRules.addRuleTable(
	"ExternalGreetingReverseOrder", //table name
	"defineGreeting", 		//template name
	new String[] { "A1","C1" },     //labels order differs from template order
	new Object[][] { // not all cells contains strings but other objects
		new Object[] { "Good Morning", new Integer(0),new Integer(11) },
		new Object[] { "Good Afternoon", new Integer(12),new Integer(17) },
		new Object[] { "Good Evening", new Integer(18), new Integer(21) },
		new Object[] { "Good Night", new Integer(22),new Integer(24)}
	}
);

shows several additional flavors that could be added to the ExternalRules object. First of all, you can use all optional rules and conditions along with other features available for "normal" rules and templates - as described here.  The array of Strings

new String[] { "A1","C1" }

placed just before the grid informs OpenRules Engine that this rule table starts with the action A1 following by the condition C1, thus violating the default column order in the template. The grid    Object[][] demonstrates an ability to specify not only String but any Java objects as long as they correspond to the types of parameters specified in the template.

If the type of objects inside rule tables do not correspond to the templates the proper error will be produced. For example, if you make a mistake in the first rule table:

externalRules.addRuleTable(
	"ExternalSummerGreeting", //table name 
	"defineGreeting", 	  //template name
	new String[][] {	  //rules
		new String[] {"O","11","Good Morning Summer"}, //letter "O" instead of "0"
		new String[] {"12","17","Good Afternoon Summer"},
		new String[] {"18","21","Good Evening Summer"},
		new String[] {"22","24","Good Night Summer"}
	}
);

you will receive a compilation error that will look like this:

org.openl.syntax.SyntaxErrorException: Error: For input string: "O" : java.lang.NumberFormatException

at ExternalRules#ExternalSummerGreeting?row=0&column=0&openl=

java.lang.NumberFormatException: For input string: "O"

The error message points you to the name of the invalid external table (ExternalRules#ExternalSummerGreeting) and to the coordinates of the invalid cells inside the grid (row=0&column=0).

 Step 3. Executing External Rules from a Java Program     top

The main file HelloCustomer.xls defines the Environment of our rule project as follows:

Environment
import.java hello.*
include ../include/HelloTemplates.xls

This application uses two simple Java beans: "Request" with an integer attribute "hour" and "Response" with a String attribute "result".

The main Java class RunExternalRules creates and executes an OpenRulesEngine in the standard way:

	
	String fileName = "file:rules/main/HelloCustomer.xls";
	OpenRulesEngine engine = new OpenRulesEngine(fileName,externalRules);
	System.out.println( 
	"\n=====================================================\n" +
	   "OpenRulesEngine: " + fileName + 
	"\n=====================================================\n");

	Response response = new Response();
	Request request = new Request();
	request.setHour(Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
	Object[] params = new Object[] { request, response };
	
	for (int i = 0; i < externalRules.getRuleTables().size(); i++) {
		RuleTable rules = (RuleTable)externalRules.getRuleTables().get(i);
		System.out.println(rules);
		engine.run(rules.getTableName(), params);
		System.out.println("Greeting generated by rules '" + rules.getTableName() + 
				           "' for hour " +request.hour +": " + response.result );
		System.out.println();
	}

To run the project you may double-click on the file "run.bat". Here is an expected output:

INITIALIZE OPENRULES ENGINE 5.3.0 (build 03092009) for [file:rules/main/HelloCustomer.xls]
External rules table: ExternalSummerGreeting
External rules table: ExternalWinterGreeting
External rules table: ExternalGreetingHorizontal
External rules table: ExternalGreetingReverseOrder
IMPORT.JAVA=hello.*
INCLUDE=../include/HelloTemplates.xls
[../include/HelloTemplates.xls] has been resolved to [file:<...>/rules/include/HelloTemplates.xls]

=====================================================
OpenRulesEngine: file:rules/main/HelloCustomer.xls
=====================================================

ExternalRules ExternalSummerGreeting template defineGreeting
0 11 Good Morning Summer 
12 17 Good Afternoon Summer 
18 21 Good Evening Summer 
22 24 Good Night Summer 

Greeting generated by rules 'ExternalSummerGreeting' for hour 16: Good Afternoon Summer

ExternalRules ExternalWinterGreeting template defineGreeting
0 12 Good Morning Winter 
13 16 Good Afternoon Winter 
17 22 Good Evening Winter 
23 24 Good Night 

Greeting generated by rules 'ExternalWinterGreeting' for hour 16: Good Afternoon Winter

ExternalRules ExternalGreetingHorizontal template defineGreetingHorizontal
0 11 Good Morning 
12 16 Good Afternoon 
17 22 Good Evening 
23 24 Good Night 

Greeting generated by rules 'ExternalGreetingHorizontal' for hour 16: Good Afternoon

ExternalRules ExternalGreetingReverseOrder template defineGreeting
Good Morning 0 11 
Good Afternoon 12 17 
Good Evening 18 21 
Good Night 22 24 

Greeting generated by rules 'ExternalGreetingReverseOrder' for hour 16: Good Afternoon

  top

Top