Developing a Web Application
with Spring Framework and OpenRules

Part 5 – Moving Business Logic to OpenRules

This is the fifth part of a step-by-step account of how to develop web applications using Spring framework and OpenRules. The first part described how to setup a Tomcat-based development environment and create a trivial web application. The second part added major Spring modules and a view that displays current date and time. The third part added business logic and GUI using Java, Spring, and JSP with JSTL. The fourth part added unit tests and a dialog with two views that allows a user to change customer information. In this part we will externalize business logic. We want to introduce business rules with minimal hustles. While we already localized business logic putting it in one Java class (JavaEngine) in Part 3, our objective now is to transfer the same logic to OpenRules decision tables. In the GreetingEngine implementation we only want to replace JavaEngine to OpenRulesEngine leaving all other components without changes.

Step 24 – Copy "hello.spring" to "hello.spring.openrules"

First of all, create a new directory "hello.spring.openrules". If you use Eclipse with OpenRules plugin already installed, add a new empty OpenRules project "hello.spring.openrules". Copy the content of the existing directory "hello.spring" into "hello.spring.openrules". If you work with Eclipse, make sure that your Java Build Path properties include all jars from war/WEB-INF/lib and servlet-api.jar from your tomcat-5.0.28/common/lib.

In your build.xml file change the name "hello.spring" to "hello.spring.openrules", so its initial lines will look like:
 

hello.spring.openrules/build.xml
<?xml version="1.0"?>

<project name="hello.spring.openrules" basedir="." default="usage">
<property file="build.properties"/>

<property name="src.dir" value="src"/>
<property name="web.dir" value="war"/>
<property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
<property name="name" value="hello.spring.openrules"/>

....
</project>

To make sure that a new "hello.spring.openrules" application still functions as "hello.spring" did, execute Ant targets build, deploy, and in a browser enter the url http://localhost:8080/hello.spring.openrules/hello.htm.

Step 25 – Creating Business Rules

Now we want to create business rules that express business logic of our customer greeting web application. We are assume that you are familiar with basics of OpenRules and know that OpenRules uses Excel tables to represent business rules. Our business logic was implemented in the project HelloSpring in a Java class JavaEngine  using two methods:

  1. void defineGreeting(int hour, EngineResponse response)

  2. void defineSalutation(Customer customer, EngineResponse response)

We want to externalize this logic by moving it to Excel rules tables. Let's create an Excel file HelloCustomer.xls and place it into hello.spring.openrules/src directory. In the worksheet "Decision Tables" we will create two Rules tables that will replace Java methods defineGreeting and defineSalutation:

 

This is a so called "Business View" of our rules. Hopefully this view is self-explanatory. For example, the first table states that if a parameter "hour" is between 0 and 11 then Set Greeting to "Good Morning", if between 12 and 17 then Set Greeting to "Good Afternoon", etc. Similarly the second table sets different salutations for different combinations of customer's gender, marital status an age. There is also a "Technical View" of these tables. You can get it if you click Excel "+" buttons on the left or the button [2] at the top left corner. Here it is:

 

The "Technical View" opens previously hidden 3 rows with a technical implementation of the business logic. Hopefully it is intuitive too (al least, for technical people). For example, the first table states that first two columns are condition columns with names C1 and C2, and the third column is an Action column wit a name A1. The semantic of the first condition "hour From" is expressed in a snippet of Java code:

                min <= hour

where "min" is any value entered in the first column (like 0, 12, 18, 23) and "hour" is an integer parameter of this Rules tables that is supposed to contain a current hour of day. This code tell you exactly what you mean when you say "hour is between min and max": as you can see in this case "Hour From" and "Hour To" are included what was not clear from the "Business View".

The worksheet "Launcher" contains an OpenRules table of the type "Method" that defines the current hour and call two previous decision tables:

putting it in one Java class (JavaEngine), our objective is to transfer the same logic to OpenRules decision tables. In the GreetingEngine implementation we only want to replace JavaEngine to OpenRulesEngine. The worksheet "Ranges" contains lists of possible values for Greetings, Gender, Marital Status, and Salutations. They are used by Excel only for the convenience of the user input inside decision tables.

Thus, we have externalized business rules that now can be extended and managed from Excel. The remaining steps will explain what should be done additionally to incorporate these Excel-based business rules into a Spring-based Web application. 

Step 26 – Adding OpenRules Libraries and build-files

Now we will add OpenRules jars and build files to our project. Create a subdirectory 'lib' inside 'war/WEB-INF' and copy to this subdirectory the entire content of 'openrules.config' that is a part of OpenRules 2.2.* standard installation. Actually, it could be enough if you just copy the following files:

Now we can delete JavaEngine from the package src/hello and replace it with the standard OpenRuleEngine inside GreetingEngine implementation:
 

hello.tomcat/src/hello/GreetingEngine.java
package hello;

import com.openrules.ruleengine.OpenRulesEngine;

public class GreetingEngine implements IGreetingEngine {

	private OpenRulesEngine engine;

	public GreetingEngine() {
		engine = new OpenRulesEngine("HelloCustomer.xls",getClass());
	}

	public String generateGreeting(Customer customer) {
		EngineResponse response = new EngineResponse();
		String methodName = "helloCustomer";
		Object[] objects = new Object[] { customer, response }; 
		engine.run(methodName,objects);
		
		String result = response.getGreeting() + ", " +
				response.getSalutation() + " " +
				customer.getName() + "!";
		System.out.println("Generated Greeting: " + result);
		return result;
	}
	public static void main(String[] args) {
		GreetingEngine engine = new GreetingEngine();

		Customer customer = new Customer();
		customer.setName("Robinson");
		customer.setGender("Female");
		customer.setMaritalStatus("Married");

		engine.generateGreeting(customer);
	}
}

Please note that there are no changes in other files because we continue to use the same interface with GreetingEngine.

To make sure that our rules inside this Excel file "understand" Java classes Customer and EngineResponse, we should add the following property file:
 

hello.spring.openrules/src/com/openrules/com.openrules.properties
openrules.local.imports=hello

This file includes a description of one property with a name of our Java package "hello". The directory structure is important.

We also have to add two configuration files to hello.spring.openrules/src:
 

hello.spring.openrules/src/openrules.properties
com.openrules.lang.xls.builderclass=com.openrules.forms.xls.XlsFormsOpenLBuilder

 

hello.spring.openrules/src/openrules.java.build.xml
<project default="none">

<taskdef name="openrules" classname="org.openl.conf.ant.AntOpenLTask"/>

<target name="build.openrules.java">
<property name="openrules.extends" value="org.openl.j" />
<property name="openrules.config" value="${basedir}/../lib" />

<echo message="Building openrules.java ... "/> 
<echo message="Basedir=${basedir}" />
<echo message="openrules.config=${openrules.config}" />

<ant antfile="${openrules.extends}.build.xml" 
 target="build.${openrules.extends}" 
 dir="${openrules.config}" 
/> 

<openrules category="openrules.java" extendscategory="${openrules.extends}"
 description="This is openrules extension of a ${openrules.extends}" >

  <libraries>
    <library namespace="org.openl.this">
      <javalib classname="com.openrules.tools.Methods"/>
    </library>
  </libraries>

  <types>
    <typelibrary namespace="org.openl.this">
      <javaimport all="${openrules.local.imports}"/>
      <javaimport all="com.openrules.tools"/>
    </typelibrary>
  </types>

</openrules>

</target>

</project>

During the build and deploy procedure, these files will be copied to 'war/WEB-INF/classes' and will be used in run-time to work with 'openrules.java' language configuration. Please, note that 'openrules.java.build.xml' file defines 'war/WEB-INF/lib' as our 'openrules.config' directory where all necessary OpenRules jars and a main build file (org.openl.j.build.xml) are located.

So, now we are ready to build, deploy and test our hello.spring.openrules application. Run Ant target 'deploy' with a Tomcat running. After running a browser with to http://localhost:8080/hello.openrules.tomcat/index.jsp (or from file run.html) we should see the same web client as in the Part 4.

Up  Part 4 – Adding Unit Tests and a Form to the Application