7 Working with Rules SDK Decision Point API

Oracle Business Rules SDK (Rules SDK) lets you write applications that access, create, modify, and execute rules in Oracle Business Rules dictionaries (and work with the contents of a dictionary). This chapter provides a brief description of Rules SDK and shows how to work with the Rules SDK Decision Point API.

7.1 Introduction to Rules SDK and the Car Rental Sample Application

Editing: provides a programatic way to create and modify dictionary components

Decision Point: provides an interface to access a dictionary and execute a decision function

Other than for explanation purposes, there is not an explicit distinction between these areas in Rules SDK. For example, to edit rules you also need to use the storage area of Rules SDK to access a dictionary. These parts of the Rules SDK are divided to help describe the different modes of usage, rather than to describe distinct Rules SDK APIs.

7.1.1 Introduction to Decision Point API

The Decision Point API provides a concise way to execute rules. Most users create Oracle Business Rules artifacts, including data model elements, rules, Decision Tables, and rulesets using the Rules Designer extension to Oracle JDeveloper. Thus, most users do not need to work directly with the engine, storage, or editing parts of Rules SDK.

To work with the Rules SDK Decision Point package you need to understand three important classes:

DecisionPoint: is a helper class that follows the factory design pattern to create instances of DecisionPointInstance. In most applications there should be one DecisionPoint object that is shared by all application threads. A caller uses the getInstance() method of DecisionPoint to get an instance of DecisionPointInstance which can be used to call the defined Decision Point.

A Decision Point manages several aspects of rule execution, including:

Use of oracle.rules.rl.RuleSession objects

Reloading of a dictionary when the dictionary is updated

To create a Decision Point in a Java application you need the following:

Either the name of a dictionary to be loaded from an MDS repository or a pre-loaded oracle.rules.sdk2.dictionary.RuleDictionary instance.

The name of a decision function stored in the specified dictionary.

7.1.2 How to Obtain the Car Rental Sample Application

This chapter shows a car rental application that demonstrates the use of Rules SDK and the Decision Point API. You can obtain the sample application in a ZIP file, CarRentalApplication.zip. This ZIP contains a complete JDeveloper application and project.

The source code for Oracle Business Rules-specific samples is available online at

To work with the sample unzip CarRentalApplication.zip into an appropriate directory. The car rental application project contains a rules dictionary and several Java examples using Rules SDK.

7.1.3 How to Open the Car Rental Sample Application and Project

The Car Rental sample application shows you how to work with the Rules SDK Decision Point API.

To open the car rental sample application:

Start Oracle JDeveloper.

Open the car rental application in the directory where you unzipped the sample. For example, from the File menu select Open... and in the Open dialog navigate to the CarRentalApplication folder.

In the Open dialog select CarRentalApplication.jws and click Open.

In the Application Navigator, expand the CarRentalApplication, expand Application Sources and Resources. This displays the Oracle Business Rules dictionary named CarRental.rules and several Java source files.

7.2 Creating a Dictionary for Use with a Decision Point

The car rental sample uses the Rules SDK Decision Point API with either a pre-loaded Oracle Business Rules dictionary or a repository stored in MDS. When you are working in a development environment you can use the Decision Point API with the pre-loaded dictionary signature. In a production environment you would typically use a Decision Point with the MDS repository signature.

The CarRental dictionary is pre-defined and is available in the car rental sample application.

To work with the Decision Point API you need to create a dictionary that contains a decision function (the car rental sample application comes with a predefined dictionary and decision function).

You perform the following steps to create a dictionary and a decision function:

When you use a Decision Point with Rules SDK, you call a decision function in a specified dictionary. The decision function that you call can contain one or more rulesets that are executed as part of the Decision Point.

7.2.3 How to Create Rules or Decision Tables for the Decision Function

The car rental sample includes two rulesets, one with IF/THEN rules and another containing a Decision Table. You can use either IF/THEN rules or Decision Tables or both in your application if you are using a Decision Point.

To view the rules in the car rental sample application:

In Rules Designer click the Denial Rules:if-then ruleset, as shown in Figure 7-4.

under age: this rule defines the minimum age of the driver. The rule compares the Driver instance age property to the global Minimum driver age. If the driver is under this age, then a new Denial fact is asserted. A call to the decision function collects this Denial fact, as defined in its output. The rule also calls a user-defined function, audit, to provide some auditing output about why the Denial is created.

too many accidents: this rule defines an upper threshold for the number of accidents a driver can have before a rental for the driver is denied. The rule also calls a user-defined function, audit, to provide some auditing output about why the Denial is created.

7.2.4 What You Need to Know About Using Car Rental Sample with a Decision Table

The car rental sample application includes the Denial Rules: decision table ruleset. To switch to use a Decision Table in the supplied decision function sample, move the Denial Rules:if-then from the Selected area in the decision function and add the Denial Rules: decision table ruleset, which uses a Decision Table to define similar rules, as shown in Figure 7-6.

The CarRentalProject project includes the com.example.rules.demo package that includes the car rental sample file, CarRentalWithDecisionPointUsingPreloadedDictionary.java. The project also includes several .java source files that support different variations for using Decision Point. Table 7-1 provides a summary of the different versions of the car rental sample.

This is the base class for all of the examples. It contains constant values for using the CarRental dictionary and a method createDrivers which creates instances of the Driver class.

CarRentalWithDecisionPoint

Contains a static attribute of type DecisionPoint and a method checkDriver() that invokes a Decision Point with a specified instance of the Driver class. This class includes these methods for the sample application so that both the MDS repository and pre-loaded dictionary examples can share the same checkDriver() implementation.

CarRentalWithDecisionPointUsingMdsRepository

Contains an example of creating a Decision Point that uses MDS to access and load the rule dictionary. In a production environment, most applications use the Decision Point API with MDS.

CarRentalWithDecisionPointUsingPreloadedDictionary

Contains an example of creating a Decision Point from an instance of the RuleDictionary class. This example also contains code for manually loading the dictionary to create a RuleDictionary instance.

CarRentalWithRuleSession

Contains an advanced usage of the Engine API that is documented further in the comments.

CarRentalWithRuleSessionPool

Contains an advanced usage of the Engine API that is documented further in the comments.

Denial

Contains the class that defines the Denial fact type used to create the rules and Decision Table.

Driver

Contains the class that defines the Driver fact type used to create the rules and Decision Table.

DriverCheckerRunnable

Contains the class which can be used as a thread for simulating concurrent users invoking the Decision Point.

7.3.1 How to Add a Decision Point Using Decision Point Builder

To use a Decision Point you create a DecisionPoint instance using DecisionPointBuilder, as shown in Example 7-1.

Example 7-1 shows the DecisionPointBuilder supports a fluent interface pattern, so all methods can easily be chained together when you create a Decision Point. The three most common methods for configuring the Decision Point with DecisionPointBuilder are overloaded to have the name with(). Each with() method takes a single argument of type RuleDictionary, DictionaryFQN, or String. The DecisionPointBuilder also supports similar set and get methods: getDecisionFunction(), setDecisionFunction(), getDictionary(), setDictionary(), getDictionaryFQN(), setDictionaryFQN().

The first step is to create a DecisionPointBuilder instance with code such as the following:

new DecisionPointBuilder()

The with() method using a String argument defines the name of the decision function that the Decision Point executes. Calling this method is mandatory.

.with(DF_NAME)

The DF_NAME specifies the name of the decision function you define for your application. For example for the sample car rental application DF_NAME is defined in CarRental.java as CarRentalDecisionFunction.

Call the build() method to construct and return a DecisionPoint instance.

The DecisionPoint instance is shared among all instances of the application, which is why it is a static attribute and created in a static block. Another way of initializing the DecisionPoint would be to initialize the m_decisionPoint attribute with a static method that created and returned a DecisionPoint instance.

7.3.2 How to Use a Decision Point with a Pre-loaded Dictionary

Example 7-2 shows the loadRuleDictionary() method that loads an instance of RuleDictionary from a file.

When reading or writing a dictionary directly from a file as shown in Example 7-2, ensure to set the encoding to UTF-8. If this is not done, Unicode characters used in the dictionary are corrupted. The UTF-8 option must be set explicitly in the FileInputStream or OutputStreamWriter constructor. Do not use Java classes such as FileReader and FileWriter, as these classes always use the platform default encoding which is usually an ASCII variant rather than a Unicode variant.

7.3.3 How to Use Executor Service to Run Threads with Decision Point

The car rental sample allows you to use Oracle Business Rules and simulate multiple concurrent users. Example 7-3 shows use of the Java ExecutorService interface to execute multiple threads that invoke the Decision Point. The ExecutorService is not part of the Rules SDK Decision Point API.

7.3.4 How to Create and Use Decision Point Instances

The DriverCheckerRunnable instances call the checkDriver() method. Example 7-5 shows the checkDriver() method that is defined in CarRentalWithDecisionPoint. The checkDriver() method handles invoking Decision Point with a Driver instance.

Example 7-5 Code to Create a Decision Point Instance with getInstance()

If the denials list is empty, then no Denial instances were asserted by the rules. This indicates that it is OK to rent a car to the driver. Otherwise, print the reasons why the driver rental was rejected:

Rental is allowed for Carol
Rental is allowed for Alice
Rental is allowed for Alice
Rental is allowed for Carol
Rental is denied for Bob because under age, age was 15, minimum age is 21
Mar 13, 2009 11:18:00 AM oracle.rules.rl.exceptions.LogWriter flush
INFO: Fired: under age because driver age less than minimum threshold for license number d222
Mar 13, 2009 11:18:00 AM oracle.rules.rl.exceptions.LogWriter flush
INFO: Fired: under age because driver age less than minimum threshold for license number d222
Rental is denied for Bob because under age, age was 15, minimum age is 21
Rental is allowed for Alice
Rental is allowed for Eve

7.5 What You Need to Know About Using Decision Point in a Production Environment

Example 7-7 shows the use of DictionaryFQN with DecisionPointBuilder to access a dictionary in an MDS repository. The complete example is shown in the sample code in CarRentalWithDecisionPointUsingMdsRepository.

The with() method using a String argument defines the name of the decision function that the Decision Point executes. Calling this method is mandatory.

.with(DF_NAME)

The DF_NAME specifies the name of the decision function you define for your application. For example for the car rental application this is defined in CarRental.java a CarRentalDecisionFunction.

Call only one of the other two with() methods. In this case the sample code calls a DictionaryFQN to access an MDS repository. Example 7-8 shows the routing that uses the dictionary package and the dictionary name to create the DictionaryFQN.

.with(DICT_FQN)

Call the build() method to construct and return a DecisionPoint instance.

7.6 What You Need to Know About Decision Point and Decision Tracing

The Rules SDK API contains methods to assist with processing a decision trace. These methods process a decision trace to replace the RL names used in the trace with the aliases used in the associated dictionary. This makes the decision trace naming consistent with the naming used in the Oracle Business Rules dictionary.

The basic API for processing a decision trace requires a RuleDictionary object and a DecisionTrace object:

This code shows the processing call that converts the naming in the decision trace to use the same names, with aliases, as in the dictionary.

The Rules SDK Decision Point API contains methods that allow you configure decision tracing and retrieve the resulting trace when you invoke a decision point. The trace you retrieve from the Decision Point is internally processed using the processDecisionTrace() method, thus you do not need to call this method to process the decision trace when you are working with a decision trace from a Decision Point.