The OpenRulesTM Tutorials         Home   PREV TOP NEXT User's Guide 

OpenRules API [T]

      Engine Constructors
      Engine Runs
      Undefined Methods
      Accessing Password Protected Files
      Engine Version
Rules Execution Logic
      Rules Execution Inside Decision Tables
      Multi-Hit Rules Tables
      Rules Overrides
      Single-Hit Rules Tables
Relationships among Rule Tables
Dynamic Rules Updates

Rule Engine in Multi-Threaded Environments

Integration with Java and XML

External Rules

OpenRules Implementation of JSR-94 API

OpenRules Inside JSP Applications

API  for OpenRules Forms

OpenRules provides an Application Programming Interface (API) that defines a set of commonly-used functions:

OpenRulesEngine    ►top

Engine Constructors     ►top

OpenRulesEngine is an OpenRules component that is used to execute different rule sets and methods specified in Excel files using application-specific business objects.  OpenRulesEngine can be invoked from any Java application using a simple Java API or a standard JSR-94 interface.

OpenRulesEngine is a Java class that provides an interface to execute rules and methods defined in Excel tables. You can see examples of how OpenRulesEngine is used by basic rule projects such as  HelloJava, HelloJsr94 and web applications such as HelloJsp, HelloForms, and HelloWS.  All of these sample projects come with the standard OpenRules Installation.

To use OpenRulesEngine inside your Java code you need to add an import statement for "com.openrules.ruleengine.OpenRulesEngine" and make sure that openrules.all.jar is in the classpath of your application.  This jar and all 3rd party jar-files needed for OpenRules execution can be found in the subdirectory "openrules.config/lib" of the standard OpenRules installation.  You may create an instance of OpenRulesEngine inside of your Java program using the following constructor:

    public OpenRulesEngine(String xlsMainFileName)

where xlsMainFileName parameter defines location for the main xls file.  To specify a file location, OpenRules uses an URL pseudo-protocol notation with prefixes such as "file:", "classpath:", "http://", "ftp://", "db:", etc.  Typically, your main xls-file Main.xls is located in the subdirectory "rules/main" of the your Java project.  In this case, its location may be defined as "file:rules/main/Main.xls".  If your main xls-file is located directly in the project classpath, you may define its location as "classpath:Main.xls".  If it is located at a website with the URL "", you may use this string as its exact specification.  All other xls-files that are included in (can be invoked from) this main file are described in its table "Environment".

You may also use other forms of the OpenRulesEngine constructor.  For example,

    public OpenRulesEngine(String xlsMainFileName, String methodName)

allows you to define the main method from the file xlsMainFileName that will be executed during the consecutive runs of this engine.

Example    ►top

Here is a complete example of Java module that creates and executes a rule engine (see HelloJava project):

package hello;
import com.openrules.ruleengine.OpenRulesEngine;
* A simple Java test for HelloCustomer.xls
public class RunHelloCustomer {
  public static void main(String[] args) {
    String fileName = "file:rules/main/HelloCustomer.xls";
    String methodName = "helloCustomer";
    OpenRulesEngine engine = new OpenRulesEngine(fileName);
    Customer customer = new Customer();

    Response response = new Response();
    Object[] objects = new Object[] { customer, response };,objects);
    System.out.println("Response: " +
       response.getMap().get("greeting") + ", " +
       response.getMap().get("salutation") +
       customer.getName() + "!" );

As you can see, when an instance "engine" of OpenRulesEngine is created, you can create an array of Java objects and pass it as a parameter of the method "run". 

 Engine Runs       ►top

The same engine can run different rules and methods defined in its Excel-files.  You may also specify the running method using

       setMethod(String methodName);

or use it directly in the engine run:,businessObjects);

If you want to pass to OpenRulesEngine only one object such as "customer", you may write something like that:"helloCustomer",customer);

If you do not want to pass any object to OpenRulesEngine but expect to receive some results from the engine's run, you may use this version of the method "run":

      String[] reasons = (String[])"getReasons");

Undefined Methods      ►top

OpenRulesEngine validates if all Excel-based tables and methods are actually defined and it produces a syntax error when some methods are missing. Sometimes, you want to execute a rule method/table from an Excel file but only if this method is actually present. To do this you may use you may use this version of the method "run" (available since release 5.3.2):

      boolean mayNotDefined = true;, businessObjects, mayNotDefined);

In this case, if the method "methodName" is not defined, the engine would not throw a usual runtime exception "The method ... is not defined" but rather will produce a warning and will continue to work. The parameter "mayNotDefined" may be used similarly with the method "run" with one parameter or with no parameters, e.g."validateCustomer", customer, true);

How to invoke rules from other rules if you do not know if these rules are defined? It may be especially important when you use some predefine rules names in templates. Instead of creating an empty rules table with the needed name, you want to use the above parameter "mayNotDefined" directly in Excel.  Let's say you need to execute rules tables with the names such as  "NJ_Rules" or "NY_Rules" from another Excel rules table but only if the proper state rules are actually defined. You may do it by calling the following method from your rules:

Method void runStateRules(OpenRulesEngine engine,  Customer customer, Response response)
String methodName = customer.state + "_Rules";
Object[] params = new Object[2];
params[0] = customer;
params[1] = response;, params, true);

We assume here that all state-specific rules ("NJ_Rules", "NY_Rules", etc.) have two parameters "customer" and "response".  To use this method you need to pass the current instance of OpenRulesEngine from your Java code to your main Excel file as a parameter "engine".  If you write an OpenRules Forms application, this instance of the OpenRulesEngine is always available as dialog().getEngine(), otherwise you have to provide an access to it, e.g. by attaching it to your own business object such as Customer.

By default OpenRules will produce a warning when the required Excel rules table or method is not available.  You may suppress such warning by calling:


Accessing Password Protected Excel Files       ►top
Some Excel workbooks might be encrypted (protected by a password) to prevent other people from opening or modifying these workbooks. Usually it's done using Excel Button Button image and then Prepare plus Encrypt Document.  OpenRules Engine may access password-protected workbooks by calling the following method just before creating an engine instance:


Instead of "password" you should use the actual password that protects your main and/or other Excel files. Only one password may be used by all protected Excel files that will be processed by one instance of the OpenRulesEngine created after this call. This call does not affect an access to unprotected files. The standard project "HelloJavaProtected" provides an example of the protected Excel file - use the word "password" to access the file "HelloCustomer.xls".

Note. The static method "setCurrentUserPassword" of the class OpenRulesEngine actually sets the BIFF8 encryption/decryption password for the current thread. The use of a "null" string will clear the password.

Engine Attachments  ►top

You may attach any Java object to the OpenRulesEngine using methods setAttachment(Object attachment) and getAttachment(). 

Engine Version  ►top

You may receive a string with the current version number of the OpenRulesEngine using the method getVersion().

Rules Execution Logic     ►top

When OpenRulesEngine is created it downloads the main xls-file and all other files using the "include" properties in the Environment tables.  The engine executes the rules starting with the main method defined for this particular engine run.

Relationships between Rules Inside Decision Tables  ►top

The OpenRules execution logic inside decision tables is very intuitive. OpenRules does not assume any implicit ("magic") execution logic and executes rules in the order specified by a rule designer.  All rules are executed one-by-one in the order they are placed in the rules table. There is a simple rule that governs rules execution inside a rules table:

The preceding rules are evaluated and executed first!

For standard vertical decision tables, all rules (rows) are executed in top-to-bottom order. For horizontal decision tables, all rules (columns) are executed in left-to-right order.

The execution logic of one rule (one row in the decision table) is as follows:

            IF ALL conditions are satisfied THEN execute ALL actions.

If at least one condition is violated (the proper code evaluation produces false), all other conditions in the same rule (row) are ignored and are not evaluated. 

The absence of a parameter in a condition cell means the condition is always true.  Actions are executed only if ALL conditions in the same row evaluated to be true.  Action cells with no parameters are ignored.

Multi-Hit Rules Tables   ►top

Multi-hit rules tables are the most popular decision tables used by default in all previous versions of OpenRules. A multi-hit table evaluates conditions in ALL rows before any action is executed.  Thus, actions are executed only AFTER all conditions have already been evaluated.  From this point of view, the execution logic is different from traditional programming if-then logic.  Let us consider a simple example.  We want to write a program "swap" that will do the following:

    If x is equal to 1 then make x to be equal to 2.
    If x is equal to 2 then make x to be equal to 1.

Suppose you decided to write a Java method assuming that there is a class App with an integer variable x.  The code may look like this:

    void swapX(App app) {
        if (app.x == 1) app.x = 2;
        if (app.x == 2) app.x = 1;

Obviously, this method will produce an incorrect result because of the missing "else".  This is obvious to a software developer, but may not be at all obvious to a business analyst.  However, in a properly formatted decision table the following representation would be a completely legitimate:

It will also match our plain English description above. Here is the same table with an extended technical view:

Rules Overrides in Multi-Hit Tables  ►top

There could be situations when all conditions in two or more rules (rows) are satisfied at the same time (multiple hits).  In that case, the actions of all rules (rows) will be executed, but the actions in the rows below can override the actions of the rows above.  This approach also allows a designer to specify a very natural requirement:

        More specific rules should override more generic rules!

The only thing a designer needs to guarantee is that a "more specific" rules are placed in the same decision table after a "more generic" rule.  For example, you may want to execute Action-1 every time that Condition-1 and Condition-2 are satisfied.  However, if additionally, Condition-3 is also satisfied, you want to execute Action-2.  To do this it is enough to arrange your decision table in the following way:

Condition-1 Condition-2 Condition-3 Action-1 Action-2
X X   X  
X X X   X

In this table the second rule may override the first one (as you might naturally expect).  As a practical example, you may consider a situation when rules common for the entire country should be overridden by the rules specific for a state. To implement this relationships you just have to guarantee that state-level  rules will be executed after the country-level rules.  For example, while a driving age in the US in general starts at 17, in Florida it starts at 16.  So, the proper multi-hit table may look like:

Age State Reject or Accept
< 17    Reject
>= 16 FL Accept

This table will initially reject all 16 years olds but then if they live in Florida it will override the rejection. Note that all people under 16 still will remain rejected.

Single-Hit Rules Tables  ►top

Single-hit decision tables do not allow rules overrides and stop rules execution upon the "first hit" when any rules is executed for the first time. Single-hit tables usually return some values and that's why that can be recognized by a return type different from "void".  For example, the following single-hit table

Rules String defineSalutation(Customer customer)
C1 C2 A1
customer.gender.equals(gender) customer.maritalStatus.equals(status) return salutation; 
String gender String status String salutation
Gender Marital Status Set Salutation
Male   Mr.
Female Married Mrs.
Female Single Ms.

returns a String with a salutation and stops further rules execution (note that if it was a multi-hit table it would always return "???").  

Below is an example of a real-world tax table that is used by a notorious US tax form 1040EZ to define a tax value based on a US taxpayer's income and marital status:

Rules Double defineTax(TaxReturn r)
C1 C2 A1
r.taxableIncome >= min r.taxableIncome < max if (r.marriedFillingJointly)
     return tax1;
     return tax2; 
double min double max double tax1 double tax2
Taxable Income At Least Taxable Income Less Than Tax if Single Tax if Married filing jointly
0 5 0 0
5 15 1 1
15 25 2 2
25 59 4 4
... ... ...

There are more than 1000 rows in the actual tax table and it is only natural to present it as a single-hit rules table.  If the OpenRulesEngine obtains a hit on rule #10 inside this table it would not bother to check the validity of all remaining rules.

Actually, inside single-hit tables the next rule will be validated and possibly executed only if a previous rule was not satisfied.  It allows a rule designer to naturally present rules that require "IF-THEN-ELSE" or "SWITCH" logic.

A single-hit table may have multiple actions but only the last action is the one that returns the table value.  The return value may be an object of any standard or custom Java class such but not a basic basic Java types such as "int".  

Relationships Among Rule Tables

In most practical cases business rules are not located in one file or in a single rule set, but rather are represented as a hierarchy of inter-related rules tables located in different files and directories - see Business Rules Repository. When you run OpenRulesEngine, you are executing a method from its main xls-file.  Frequently, this method defines an execution logic that uses the conditions and sequences of rules presented in other rule tables and methods.  In trivial cases, the rule engine can execute a rule table directly from a Java program. Typically, the main method executes a launcher that is a simple method or a rules table that specifies the execution sequence for other rules tables.

Because OpenRules interprets rules tables as regular methods, designers of rules frequently create special "processing flow" decision tables to specify the conditions under which different rules should be executed.  See examples of processing flow rules in such sample projects as Loan2 and LoanDynamics.  One way or another, a rule designer needs to explicitly specify the execution logic for different rule sets.

Dynamic Rules Updates

If a business rule is changed, OpenRulesEngine automatically reloads the rule when necessary.  Before any engine's run, OpenRulesEngine checks to determine if the main Excel file associated with this instance of the engine has been changed.  Actually, OpenRulesEngine looks at the latest modification dates of the file xlsMainFileName.  If it has been modified, OpenRulesEngine re-initializes itself and reloads all related Excel files.  You can shut down this feature by executing the following method:



Rule Engine in Multi-Threaded Environments

OpenRulesEngine is thread-safe and works very efficiently in multi-threaded environments supporting real parallelism. Contrary to many other rule engines, OpenRules' rule engine is stateless. It allows a user to create only one instance of the class OpenRulesEngine, and then share this instance between different threads - there are no needs to create a pool of rule engines. A user may also initialize the engine with application data common for all threads, and attach this data directly to the engine using the methods setAttachment(Object attachment). Different threads will receive this instance of the rule engine as a parameter, and will safely run various rules in parallel using the same engine.

OpenRules installation (starting with v.5.3.1) includes an example "HelloFromThreads" that demonstrates how to organize a parallel execution of the same OpenRulesEngine's instance in different threads and how to measure their performance.

Integration with Java and XML     ►top

Java Classes

OpenRules allows you to externalize business logic into xls-files.  However, these files still can use objects and methods defined in your Java environment.  For example, in the RulesRepository example all rule tables deal with a Java object Appl defined in the Java package myjava.package1.  So, the proper Environment table inside file Main.xls (see above) contains a property "" with value "myjava.package1.*":

The property "" allows to define all classes from the package following the standard Java notation, for example "hello.*".  You can also import only specific class your rules may need as in an example above.  You may define a separate property "" for every used Java package or merge the property "" in one cell with many rows for different Java packages.  Here is a more complex example:

include ../include/Rules1.xls

Naturally the proper jar-files or Java classes should be in the classpath of your Java application that uses these rules.

If you want to use static Java methods defined in some standard Java libraries and you do not want to specify their full path, you can use the property "import.static".  The static import declaration imports static members from Java classes, allowing them to be used in Excel tables without class qualification.  For example, many OpenRules sample projects use static methods from the standard Java library that includes class Methods.   So, many Environments tables have property "import.static" defined as "".  It allows you to write out("Rules 1")  instead of  Methods.out("Rules 1").

XML Files

Along with Java classes, OpenRules tables can use objects defined in XML files.  For example, the standard sample project HelloXMLCustomer uses an object of the type Customer defined in the file Customer.xml located in the project classpath:


The xls-file HelloXmlCustomer.xls that deals with this object includes the following Environment table:

The property "import.schema" specifies a location of the proper xml-file, in this case "classpath:/Customer.xml".  Of course, you can use any other location in your local file system that starts with the prefix "file:".  This example also tells you that this Excel file uses:

  1. static Java methods defined in the standard OpenRules package ""
  2. xml-file "classpath:/Customer.xml"
  3. Java class "Response" from a package "hello"
  4. include-file "HelloRules.xls" that is located in the subdirectory "include" of the directory where the main xls file is located.

The object of the type "Customer" can be created using the following API:

    Customer customer = Customer.load("classpath:/Customer.xml");

You may use more complex structures defined in xml-files. For example, the project HelloXMLPeople uses the following xml-file:

<?xml version="1.0" encoding="UTF-8"?>
<People type="Array of Person(s)">
           <Person name="Robinson" gender="Female" maritalStatus="Married" age="55" />
           <Person name="Robinson" gender="Female" maritalStatus="Single" age="23" />
           <Person name="Robinson" gender="Male" maritalStatus="Single" age="17" />
           <Person name="Robinson" gender="Male" maritalStatus="Single" age="3" />

Then the method that launches greeting rules for every Person from an array People is defined as:


External Rules   ►top

Starting with the release 5.3 OpenRules provides a generic Java API for adding business rules defined in different external sources. 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 such as

ExternalRules externalRules = new ExternalRules();

and then add different rule tables using the method:

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

This simple interface give a developer an ability to bring rules from any external source and add them to OpenRulesEngine as regular Java objects.

Here are other flavors of the ExternalRules' method "addRuleTable":

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

This method could be useful when you want to take advantage of optional or partially defined actions and conditions inside the proper rule template - see an example here.

The method

        addRuleTable(String ruleTableName,
                              String ruleTemplateName,
                              Objects[] ruleGrid)

is used to avoid two-dimensional arrays. For example, it could be useful when you use form ExternalRules object directly in Excel where OpenRules does not allow multi-dimensional arrays - see example ExternalRulesFromXML.htm.

The described methods are predefined implementations of a more generic method

        addRuleTable(IRuleTable table)

where the interface IRuleTable is described as:

public interface IRuleTable {

public String getTableName();

public String getTemplateName();

public IRuleProvider getRules();



You may look at the source code of the standard RuleProvider in the package com.openrules.table.external and/or write your own custom RuleProvider that provides a custom implementation of the interface IRuleTable.

If the rules in the external source where changed, you may notify the ExternalRules object about this fact by using the method


Then during the next rule engine's run, all rules will be dynamically reloaded. 

OpenRules provides five sample projects that demonstrate how to use External Rules:

ExternalRulesFromJava: shows how to define rules as Java objects
ExternalRulesFromDB: shows how to define rules in MS Access using JDBC
ExternalRulesFromXML: shows how to define rules in XML files
ExternalRulesFromExcel: shows how to define rules as Excel Data tables
shows how to build a web application that allows a user to change and execute rules on the fly without a restart


OpenRules Implementation of JSR-94 API   ►top

OpenRules provides a reference implementation of the JSR94 standard known as Java Rule Engine API (see  The standard OpenRules installation includes the following projects:

JSR-94 Project  Description
lib.jsr94 This project contains the standard jsr94-1.0 library
com.openrules.jsr94 This is an OpenRules's reference implementation for the JSR94 standard and includes the source code. It uses OpenRulesEngine to implement RuleExecutionSet
HelloJsr94 This is an example of using JSR94 for simple rules that generate customized greetings
HelloJspJsr94 HelloJspJsr94 is similar to HelloJsp but uses the OpenRules JSR-94 Interface to create and run OpenRulesEngine for a web application.

OpenRules Inside JSP Applications   ►top

OpenRulesEngine can be naturally used to incorporate business rules inside a Web Application.  The standard installation comes with a sample project "HelloJSP" that demonstrates how to create a simple web application with business logic presented in OpenRules and presentation logic - in JSP.  Here is how it works.

In the Java package "hello" we created a class GreetingEngine that encapsulates OpenRulesEngine with the main xls-file defined relative to the directory from which a Tomcat server will start:

public GreetingEngine() {
       String fileName = "file:../webapps/HelloJsp/rules/HelloCustomer.xls";
= new OpenRulesEngine(fileName,getClass());

The GUI layout is described at war/index.jsp. Inside this jsp-file we create GreetingEngine described as has shown in the code below:

<%@ page import = "hello.Customer" %>
<jsp:useBean id="customer" class="hello.Customer" scope="session"/>
<jsp:setProperty name="customer" property="*"/>
<jsp:useBean id="engine" class="hello.GreetingEngine" scope="session"/>

<body bgcolor="lightblue">
<font size=4>
Welcome to the Hello Customer example.
<br>Enter Customer data and click "Generate Greeting"<br><br>

<form method=post><hr><br>

Customer Name: <input type=text name=name value=<%= customer.getName() %>>
Customer Gender:
<input value="Female" type="radio" name=gender
<% if (customer.getGender().equals("Female")) {%> checked="true" <%}%>
<input value="Male" type="radio" name=gender<% if (customer.getGender().equals("Male")) {%> checked="true" <%}%>

Customer Age: <input type=int name=age value=<%= customer.getAge() %> > <p>
Customer Marital Status:
<input value="Single" type="radio" name=maritalStatus
<% if (customer.getMaritalStatus().equals("Single")) {%> checked="true" <%}%>
<input value="Married" type="radio" name=maritalStatus
<% if (customer.getMaritalStatus().equals("Married")) {%> checked="true" <%}%>

<input type=submit value="Generate Greeting">


Generated Greeting:
<b><%= engine.generateGreeting(customer) %></b><br><hr></font>


After describing input fields of this simple form that collects basic customer information, the engine will generate the proper greeting by executing the method "generateGreeting".  This method simple runs an underlying OpenRulesEngine executing business rules defined in the file war/rules/HelloCustomer.xls.  Thus, OpenRulesEngine becomes a regular component of this JSP-based application.

API  for OpenRules Forms   ►top

OpenRules provides a special API (a few Java classes) to support a simplified, fast way to create dynamic web content using Excel-based rules and forms.  OpenRules approach enables rapid development of web-based applications that are server- and platform-independent.  While one can choose OpenRules in conjunction with any other web development technology like JSP (see HelloJsp example above), OpenRules also supports its own Excel-based  Web GUI development known as "OpenRules Forms".

To integrate OpenRules Forms into a web application, you can use two OpenRules classes:

Here is an example of an index.jsp file that utilizes these classes:

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

String xlsMain = "file:../webapps/HelloForms/rules/main/HelloWeb.xls";
String session_attr = "openrules_session";
OpenRulesSession openrulesSession = (OpenRulesSession) session.getAttribute(session_attr);
if (openrulesSession == null ) {
    System.out.println("NEW OPENRULES SESSION");
    openrulesSession = new OpenRulesSession(xlsMain);
    session.setAttribute( session_attr, openrulesSession);
Customer customer = new Customer();

    EngineResponse engineResponse = new EngineResponse();

    Dialog dialog = openrulesSession.getDialog();

    Customer savedCustomer = new Customer();


     <HEAD><TITLE> hello.openrules.forms </TITLE></HEAD>
          <%    openrulesSession.processRequest(session, request, out);  %>

This example demonstrates how to create an OpenRulesSession as part of the standard HttpSession and process the standard HttpServletRequest.  An instance of OpenRulesSession "openrulesSession" automatically creates an underlying OpenRulesEngine based on the main xls-files passed to the session as a parameter.  This instance of OpenRulesEngine is available to you through the public method:

        OpenRulesEngine getOpenRulesEngine();

OpenRulesSession also creates and provides an access to the underlying Dialog object using the public method :

        Dialog getDialog();

Because the Dialog is a subclass of the standard Java HashMap you can attach your own business objects to the dialog.  In the example above, we created an object Customer (from a Java package "hello") during the OpenRulesSession creation and put it into the dialog using the method:


The Dialog object is always passed to the main Rules method ("main" or "body").  During every request/response iteration, rules methods (described in Excel) can access business objects put in the dialog, e.g.:

        Customer customer = (Customer) dialog().get("customer");

OpenRulesSession uses only one OpenRulesEngine.  However, because the engine is available to you, you can define different methods and business objects for the engine to run. Thus, using one main xls-file with multiple methods (potentially located in multiple included xls-files) you can run different methods as different "engines".