Open Your Business Rules!                     
Rules-based Operational Decision Services

External Rules Coming From GUI

Rule Project "ExternalRulesFromGUI"

Step 1. Defining GUI
Step 2. Defining Implementation Approach

Step 3. Setting Up Rule Templates

Step 4. Supporting Java Classes

Step 5. Creating Graphical Form Layouts in Excel
Step 6. Deploying and Executing the Web Application

OpenRules allows you to keep your business rules in Excel data tables that correspond to the columns (conditions and actions) of Excel's templates based on which the proper rule tables will be executed. 

Step 1. Defining Graphical User Interface

This project intends to create a web application that will consist of two parts:

1) Data input and Rule Engine Execution

2) Online Rules Editing

The view "Generate Customer Greeting" will allow to enter basic information about a customer and generate a greeting like "Good Morning, Mrs. Robinson!" based on the current time. Here is an example of the proper view:

By clicking on the button "Generate Greeting" a user could produce a new greeting in accordance with the latest greeting and salutation rules. By clicking on the buttons "Greeting Rules" a user will be taken to a web-based rule editor to modify the Greeting Rules:

By clicking on the buttons "Salutation Rules" a user will be taken to a web-based rule editor to modify the Salutation Rules:

This editors shows not how to make changes in the rule attributes but also allows a user to add rules by clicking on "the hyperlink "Add Rule" or to delete rules by clicking on the red cross.

Step 2. Defining Implementation Approach       top

We will build this web application using OpenRules Forms by defining 3 Excel-based layouts for every of the above views and using navigation logic described as processing flow rules. We will deploy our application on the Tomcat server. As usual, we will create the following files:

File Directory Purpose
HelloExternalRulesFromGUI.xls ./war/rules/main Describes the Environment table and the main method that will be executed during every interaction with a web client
HelloForms.xls ./war/rules/gui Describes all screen layouts and processing flow rules
Dialog.xls ./war/rules/gui The standard OpenRules file borrowed from the project openrules.forms.lib
HelloData.xls ./war/rules/data Rule templates
index.jsp ./ The entry point to this JSP-based web application

What makes this application special is a need to reinitialize the rule engine that generates a greeting every time when the greetings and/or salutations have been modified. However, we do not have to reinitialize a rule engine associated with an already opened OpenRulesSession with all layouts and related rule tables. So, we have to carefully distributes greeting generation information and GUI information between two different rule engines making sure that re-initialization of the first engine dome really quickly.

When we start the application for the first time, we want to display the default rules (defined in an Excel file) and we also want to use the default data about a customer (defined in another Excel file).

In this implementation, we will define a special Java class HelloManager whose responsibilities will include these and other data management tasks. The manager will support two rule engines:

  1. A rule engine that reads the default greeting and salutation rules from the file war/rules/main/HelloDefaultRules.xls. Only this engine will deal with greeting rules and rule templates presented in the file war/rules/logic/HelloTemplates.xls.
     
  2. A rule engine associated with the OpenRulesSession that will handle all GUI problems and will also read the default data about a customer from the Excel file HelloData.xls.

Thus, the entry point to our web application "index.jsp" will look as follows:

<%@ page import="com.openrules.forms.gui.jsp.*" %>

<%@ page import="com.openrules.forms.*" %>

<%@ page import="hello.rules.*" %>

<%@ page import="com.openrules.ruleengine.*" %>
 

<%

String s_attr = "openrules_session";

OpenRulesSession openrules_session = (OpenRulesSession) session.getAttribute(s_attr);

if (openrules_session == null ) {

    // Create manager using data from HelloDefaultRules.xls

    String xlsMainRules = "file:./webapps/HelloExternaRulesFromGUI/rules/main/HelloDefaultRules.xls";

    HelloManager man = new HelloManager(xlsMainRules);

    // Create OpenRulesSession using HelloExternaRulesFromGUI.xls

    String xlsMainForms = "file:./webapps/HelloExternaRulesFromGUI/rules/main/HelloExternaRulesFromGUI.xls";

    openrules_session = new OpenRulesSession(xlsMainForms);

    session.setAttribute( s_attr, openrules_session);

    System.out.println("NEW SESSION based on " + xlsMainForms);

    man.setFormsEngine(openrules_session.getOpenRulesEngine());

    // Read default rules and data from Excel files

    man.getDefaults();

    Dialog dialog = openrules_session.getDialog();

    dialog.put("manager",man);

}

%>

<HTML><HEAD><TITLE>OpenRules</TITLE></HEAD>

<body>

<%

     System.out.println("PROCESS REQUEST");

     openrules_session.processRequest(session, request, out);

%>

</body>

</HTML>

 

The first rule engine will be created by the constructor HelloManager(xlsMainRules), and the second rule engine automatically created by the OpenRulesSession will be set for the HelloManager by the statement:

       man.setFormsEngine(openrules_session.getOpenRulesEngine());

The Environment table for the first rule engine is located in the file HelloDefaultRules.xls:

 

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

The Environment table for the second rule engine is located in the file HelloExternaRulesFromGUI.xls:

Environment
import.static com.openrules.tools.Methods
import.java hello.rules.*
include ../gui/Dialog.xls
../data/HelloData.xls
../gui/HelloForms.xls

The main execution loop is implemented by the following method:

Method TableLayout main(Dialog dialog) 
HelloManager man = (HelloManager) dialog().get("manager");
if (man == null)
   return fatalErrorLayout("HelloManager is not defined if index.jsp");
defineNextProcessingStep(man);
if (dialog().errors == 0)
{     
    processingFlowRules(man);
    defineNextProcessingStep(man);
}
return mainLayout();

 

Step 3. Setting Up Rule Templates       top

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

Rules void defineGreeting(App app, int hour)
C1 C2 A1
min <= hour hour <= max

app.greeting =  greeting; 

int min int max String greeting
Hour From Hour To Set Greeting
    Unknown Greeting

specifies how to define different greetings (Good Morning, Good Afternoon, etc.) based on the hour of the day. If the parameter "hour" belongs to the interval [min;max] defined by a concrete rule then the attribute "greeting" of the parameter "app" will be set to the proper greeting. If no rules are satisfied, this multi-hit table will use the default greeting "Unknown Greeting". 

The second template

Rules void defineSalutation(App app, Customer c)
C1 C2 C3 A1
c.gender.equals(gender) c.maritalStatus.equals(status) c.age < age

app.salutation = salutation; 

String gender String status int age String salutation
Gender Marital Status Age Less Than Set Salutation
      Unknown Salutation

specifies how to define different salutations (Mr., Mrs., etc.) based on customer attributes Gender, Marital Status, and Age. If no rules are satisfied, this multi-hit table will use the default salutation "Unknown Salutation". 

 

Step 4. Creating Supporting Java Classes    top

We define a Java package "hello.rules" with the following classes:

Customer (Customer.java)

  • String name
  • String gender
  • String maritalStatus
  • int age

App (App.java)

  • Customer customer
  • String greeting
  • String salutation

GreetingRule (GreetingRule.java)

  • int from
  • int to
  • String greeting

These classes are basic Java beans used inside rules and forms. To demonstrate the use of a more complex rule editor, we will implement the rule table for salutation rules as an OpenRules dynamic table. To do this we will define two classes:

SalutationRule implementes Checkable (SalutationRule.java)

  • String gender
  • String maritalStatus
  • String maxAge
  • String salutation
  • HelloManager manager

and the class SalutationRules that extends DynamicTable (SalutationRules.java) by defining two methods:

public String getHeaderLayoutName() {

        return "salutationsTableHeader";

}

public String getRowLayoutName() {

        return "salutationsTableRow";

}

 

And finally the main Java class  is a placeholder for all other objects:

HelloManager (HelloManager.java)

  • OpenRulesEngine ruleEngine

  • OpenRulesEngine formsEngine

  • GreetingRule[] greetingRules

  • SalutationRule[] defaultSalutationRules

  • SalutationRules salutationRules

  • App app

  • ExternalRules externalRules

The object "ruleEngine" is defined in the constructor for the object "formsEngine" defined in the index.jsp. At the application initialization the manager executes the method "getDefaults":

 

public void getDefaults() {

	greetingRules = (GreetingRule[])ruleEngine.run("getDefaultGreetingRules");
	
	defaultSalutationRules = (SalutationRule[])ruleEngine.run("getDefaultSalutationRules");
	salutationRules = new SalutationRules(formsEngine);
	for (int i = 0; i < defaultSalutationRules.length; i++) {
		SalutationRule rule = defaultSalutationRules[i];
		rule.setManager(this);
		salutationRules.addNewRow(rule);
	}
	
	createExternalRules();
	externalRules.setModified(true);
	ruleEngine.log("There is " + getExternalRules().getRuleTables().size() + " external tables");
	
	Customer customer = (Customer) formsEngine.run("getDefaultCustomer");
	app = new App();
	app.setCustomer(customer);
}

 

This method receives the greetingRules from the file HelloDefaultRules.xls using the method "getDefaultGreetingRules".  It receives the defaultSalutationRules using the method "getDefaultSalutationRules" and then creates salutationRules to support the proper dynamic graphical table. Then it creates an instance of the type ExternalRules using this method:

 

public void createExternalRules() {
		
	String[][] greetingGrid = new String[greetingRules.length][3];
	for (int i = 0; i < greetingRules.length; i++) {
		GreetingRule rule = greetingRules[i];
		greetingGrid[i] = new String[] { Integer.toString(rule.from), Integer.toString(rule.to), rule.greeting };
	}
	
	String[][] salutationGrid = new String[salutationRules.getRows().size()][4];
	for (int i = 0; i < salutationRules.getRows().size(); i++) {
		SalutationRule rule = (SalutationRule)salutationRules.getRows().get(i);
		salutationGrid[i] = new String[] { rule.gender, rule.maritalStatus, rule.maxAge, rule.salutation };
	}
	
	externalRules = new ExternalRules();
	externalRules.addRuleTable(
		"greetingRules", 	//table name 
		"defineGreeting", 	//template name
		greetingGrid);
	
	externalRules.addRuleTable(
		"salutationRules", 	//table name 
		"defineSalutation", //template name
		salutationGrid);
	
	externalRules.setModified(false);
	ruleEngine.setExternalRules(externalRules);
}

And finally the manager creates the default application "app" with a customer received from the file HelloData.xls:

Data Customer customers
customer.name customer.maritalStatus customer.gender customer.age
Customer Name Marital Status Gender Age
Robinson Married Female 24
Smith Single Male 19
     
     
Method Customer getCustomer()  
return customers[0];  

Step 5. Creating Graphical Layouts in Excel     top

All GUI realted forms and rules are descibed in the file HelloForms.xls.  The mainLayout specifies a general layout for all three layout:

Layout TableLayout mainLayout()
properties width 100%
cellspacing 4
cellpadding 2
border 1
style background-color:lightblue
dialog().nextLayout
<a href="http://openrules.com"> <font size="1" face="Arial" color="blue"> OpenRules, Inc. </font></a>

The layout "GenerateGreeting":

Layout TableLayout generateGreetingLayout(App app, Customer c)
<h3>Generate Customer Greeting </h3> 
currentTime()
"Name:" [c.name]
"Age:" [c.age]
"Gender:" [c.gender]["Male,Female"]
"Marital Status:" <F type="radio" >[c.maritalStatus]["Single,Married"] </F> 
<hr/>
actionButton("Generate Greeting"); actionButton("Greeting Rules"); actionButton("Salutation Rules");
"Generated Greeting:" <strong><C> app.result </C></strong>

There two layouts to support "GreetingRules":

Layout TableLayout greetingRulesLayout(HelloManager man)
<h3>Greeting Rules</h3> 
<strong>Rules "Define Greeting" </strong>
greetingRulesTable(man);
actionButton("Save Changes"); actionButton("Salutation Rules"); actionButton("Generate Greeting");
     
Layout TableLayout greetingRulesTable(HelloManager man)
<b>Hour From</b> <b>Hour To</b> <b>Greeting</b>
[man.greetingRules[0].from] [man.greetingRules[0].to] [man.greetingRules[0].greeting][getPossibleGreetings()]
[man.greetingRules[1].from] [man.greetingRules[1].to] [man.greetingRules[1].greeting][getPossibleGreetings()]
[man.greetingRules[2].from] [man.greetingRules[2].to] [man.greetingRules[2].greeting][getPossibleGreetings()]
[man.greetingRules[3].from] [man.greetingRules[3].to] [man.greetingRules[3].greeting][getPossibleGreetings()]

This form has a fixed number of rules (row), so a user may change only values of rules attributes.

The layouts "SalutationRules" represent a dynamic table:

Layout TableLayout salutationRulesLayout(HelloManager man)
<h3> Salutation Rules</h3> 
<strong>Rules "Define Salutation" </strong>
man.salutationRules.createTable();
actionHyperlink( "Add Rule");
actionButton("Save Changes"); actionButton("Greeting Rules"); actionButton("Generate Greeting");

 

Layout TableLayout salutationsTableHeader()
<b>Gender</b> <b>Marital Status</b> <b>Age Less Than</b> <b>Salutation</b> <b>Delete</b>

 

Layout TableLayout salutationsTableRow(SalutationRule rule)
[rule.gender]["Male,Female"] [rule.maritalStatus]["Married,Single"] [rule.maxAge] [rule.salutation][getPossibleSalutations()] deleteRuleButton(rule);

 

Layout TableLayout deleteRuleButton(SalutationRule rule)
<F  type="image" src="../openrules.forms.lib/images/delete.png">
     [][] [rule.manager.salutationRules.deleteRow(rule); dialog().setLastAction("Delete Rule")] 
</F>

Her is the rule table that specifies processing flow:

Rules void processingFlowRules(HelloManager man)
IF
Current Step is
AND
Action is
THEN
Execute Code
AND
Go To The Step
  Init   GenerateGreeting
GenerateGreeting   { man.cleanUp(); } GenerateGreeting
GenerateGreeting Generate Greeting { man.generateGreeting(); } GenerateGreeting
GenerateGreeting Greeting Rules   GreetingRules
GenerateGreeting Salutation Rules   SalutationRules
GreetingRules Save Changes { man.updateRules(); } GreetingRules
GreetingRules Salutation Rules   SalutationRules
GreetingRules Generate Greeting   GenerateGreeting
SalutationRules Save Changes { man.updateRules(); } SalutationRules
SalutationRules Add Rule { man.addSalutationRule(); } SalutationRules
SalutationRules Delete Rule   SalutationRules
SalutationRules Greeting Rules   GreetingRules
SalutationRules Generate Greeting   GenerateGreeting

As you can see, the action "Save Changes" leads to the execution of the manager's method "updateRules":

	public void updateRules() {
		createExternalRules();
		getExternalRules().setModified(true);
		showRules();
	}

 This method will create a new instance of the external rules (based on the latest changes introduced by rule editors), will mark external rules as "modified" that will force a rule engine to reinitialize itself before next run of the method "generateGreeting":

	public void generateGreeting() { 
		ruleEngine.run("greetingRules",app);
		ruleEngine.run("salutationRules",app);
	}

Step 6. Deploying and Executing the Web Application

To deploy this web application on the Tomcat server specified in the file build.properties, it is enough to double-click on deploy.bat.  To start the application make sure that your Tomcat is up and running and double-clock on run.bat.

top

 

Top