8 Working with Rules in Standalone (Non SOA/BPM) Scenarios

When using rules in standalone (non SOA or BPM) scenarios, you can create RuleSession rules, or you can use the Decision Point API.

For more information about using a RulesSession object, see Using a RuleSession in Rules Language Reference for Oracle Business Process Management.

For information about using the Decision Point API, see Introduction to the Rules SDK Decision Point API.

This chapter includes the following sections:

For more information on APIs that are referred to in this chapter, see Java API Reference for Oracle Business Rules.

8.1 Loading a Dictionary from the Repository

Non-SCA (SOA/BPM) applications typically package the rule dictionaries used by the application such that they are copied to the MDS repository when the application is deployed. In order to use the dictionaries at runtime, they will need to be retrieved from MDS. The basic access method is to use the RuleRepository API to access the dictionaries. A simple usage example is shown below.

RuleRepository rr = RepositoryManager.getMDSRuleRepository(null);
 // pkg and name are the dictionary package and name (Strings).
 // Alternatively you could construct a DictionaryFQN
 RuleDictionary rd = rr.load(pkg, name);
 // if this is an editing session, edit session occurs and
 // then save it when done.
 rr.save(rd);
 // when the RuleRepository will not be used again it must be closed.
 rr.close();

It is typical that an application will want to react when a dictionary has been modified, reload the dictionary and begin using the new rule definitions. Detecting when a dictionary must be reloaded is complicated when linked dictionaries are used since it may not be the root dictionary that was modified.

In this situation, the oracle.rules.sdk2.repository.DictionaryLoader class is the recommended mechanism for loading dictionaries for rule execution. DictionaryLoader tracks the dictionaries that are loaded including linked dictionaries and can determine when a dictionary it has loaded needs to be reloaded. DictionaryLoader uses DictionaryFinder instances to load all dictionaries. DictionaryFinders are added to a DictionaryLoader instance with the addFinder method in the order in which they will be invoked to find a dictionary. That is, the first finder added will be the first one to attempt to load a dictionary. When all the desired DictionaryFinders have been added to the DictionaryLoader, the loadDictionary() method is used to load a dictionary. The reloadNeeded method can be invoked to determine if a dictionary needs to be reloaded.

 //
  // A RuleRepository instance is needed for its built-in DictionaryFinder
  //
  RuleRepository rr = RepositoryManager.getMDSRuleRepository(null);
  DictionaryFinder rrf = rr.getDictionaryFinder();
 
  //
  // Create the dictionary loader
  //
  DictionaryLoader dloader = new DictionaryLoader();
  dloader.addFinder(rrf);
  //
  // If the DecisionPointDictionaryFinder is required, add it
  //
  dloader.addFinder(new DecisionPointDictionaryFinder());
 
  //
  // Load the dictionary
  //
  DictionaryFQN fqn = new DictionaryFQN("somepackage", "myDictionary");
  RuleDictionary rd = dloader.loadDictionary(fqn);
 
  //
  // Check if the dictionary needs to be reloaded
  //
  if (dloader.reloadNeeded(fqn))
      rd = dloader.loadDictionary(fqn);
 
  //
  // When usage is complete, the RuleRepository must be closed.
  //
  rr.close();

8.2 Executing a Rule Dictionary

There are two approaches to initializing the RuleSessionPool from the RuleDictionary: initiallizing the RuleSessioPool, and using the Decision Point API.

For information, see Introduction to the Rules SDK Decision Point API

When initializing for rule execution, once a RuleDictionary has been loaded a RuleSessionPool should be initialized with RL generated from the dictionary.

For more information, see How to Use a RuleSession Pool in the Rules Language Reference for Oracle Business Process Management.

If a single decision function will be invoked, then it is most efficient to load only the rule sets that are referenced by that decision function. Sample code to build the list of RL text which is passed to the RuleSessionPool constructor is shown below.

Note that error checking and exception handling not shown for brevity.

RuleDictionary rd;  // previously loaded dictionary
        String dfAlias = "Alias for my Decision Function";
        DecisionFunction df =
 rd.getCombinedDataModel().getDecisionFunctionByAlias(dfAlias);
        List<String> rlList = new ArrayList<String>();
        //
        // Add the RL for the data model
        //
        rlList.add(rd.dataModelRL());
        //
        // Add the RL for each rule set referenced by the decision function
        //
        Collection<String> rsal = df.getRuleSets();
        for (String alias : rsal)
        {
            rlList.add(rd.ruleSetRL(alias));
        }

If multiple decision functions will be invoked from the same RuleSessionPool, then adding the RL for the rulesets referenced by each decision function will enable this. Care must be taken to avoid adding the same ruleset twice.

In other scenarios such as using rules to dynamically selecting other rule sets to execute at run time, it will be necessary to load all of the rule sets in the dictionary. Sample code to do this is shown below.

RuleDictionary rd;  // previously loaded dictionary
        List<String> rlList = new ArrayList<String>();
        //
        // Add the RL for the data model
        //
        rlList.add(rd.dataModelRL());
        //
        // Add the RL for each rule set referenced by the decision function
        //
        Collection<String> rsal = rd.getRuleSetAliases(true);
        for (String alias : rsal)
        {
            rlList.add(rd.ruleSetRL(alias));
        }

8.3 Introduction to the Rules SDK Decision Point API

This section describes how to use Oracle Business Rules SDK (Rules SDK) to write applications that access, create, modify, and execute rules in Oracle Business Rules dictionaries (and work with the contents of a dictionary). It also provides a brief description of Rules SDK and shows how to work with the Rules SDK Decision Point API. The Rules SDK consists of four areas:

  • Engine: provides for rules execution

  • Storage: provides access to rule dictionaries and repositories

  • 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.

8.3.1 Working with 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.

  • DecisionPointBuilder: follows the Builder design pattern to construct a Decision Point.

  • DecisionPointInstance: users call invoke() in this class to assert facts and execute a decision function.

The DecisionPoint classes support a fluent interface model so that methods can be chained together. For more information, see

http://www.martinfowler.com/bliki/FluentInterface.html

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.

8.3.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 and SOA samples are available online in the Oracle SOA Suite samples page.

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.

For more examples, see Introduction to the Grades Sample Application

8.3.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:

  1. Start Oracle JDeveloper.
  2. 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.
  3. In the Open dialog select CarRentalApplication.jws and click Open.
  4. 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.

8.4 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:

8.4.1 How to Create Data Model Elements for Use with a Decision Point

Note:

Note that the screen shots reflect a previous version, however, the content is applicable to the current release.

You need the following to add to a decision function when you create an application with a Decision Point.

To view the data model in the sample application:

  1. In Rules Designer, click the Facts navigation tab.
  2. Select the Java Facts tab, as shown in Figure 8-1.

    The Java Facts tab shows four fact types imported, in addition to the fact types provided as built-in to the dictionary.

    The Driver Java Fact is imported from the Driver Java class in the project.

    The Denial Java Fact is imported from Denial Java class in the project.

    The LicenseType and VehicleType facts are imported from the nested enum classes defined in the Driver class.

    Figure 8-1 Defined Java Facts for the Car Rental Sample Application

    Description of Figure 8-1 follows
    Description of "Figure 8-1 Defined Java Facts for the Car Rental Sample Application"

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.

Similarly, to view the ruleset in the supplied car rental sample application, expand the CarRentalApplication in Rules Designer. In the CarRentalApplication, expand Resources and double-click the CarRental.rules

8.4.2 How to View a Decision Function to Call from the Decision Point

When you work with the Decision Point API you use decision functions to expose an Oracle Business Rules dictionary. For more information on decision functions, see Working with Decision Functions.

To view the decision function in the car rental sample application:

  1. In Rules Designer, click the Decision Functions navigation tab. This displays the available decision functions in the CarRental dictionary, as shown in Figure 8-2.

    Figure 8-2 Car Rental Sample Decision Function

    Description of Figure 8-2 follows
    Description of "Figure 8-2 Car Rental Sample Decision Function"
  2. Select the row with CarRentalDecisionFunction and double-click the decision function icon. This opens the Edit Decision Function dialog as shown in Figure 8-3.

    The decision function Inputs table includes a single argument for a Driver fact type.

    The decision function Outputs table includes a single argument for a Denial fact type.

    The decision function Rulesets and Decision Functions area shows Denial Rules:if-then in the Selected box.

    Figure 8-3 Car Rental Decision Function for the Car Rental Sample Application

    Description of Figure 8-3 follows
    Description of "Figure 8-3 Car Rental Decision Function for the Car Rental Sample Application"

8.4.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:

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

    Figure 8-4 Ruleset with IF/THEN Rules for the Car Rental Sample Application

    Description of Figure 8-4 follows
    Description of "Figure 8-4 Ruleset with IF/THEN Rules for the Car Rental Sample Application"

    The Denial Rules:if-then ruleset includes two rules:

    • 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.

    • 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.

  2. To view the Decision Table in the car rental application, click the Denial Rules:decision table ruleset in the Rules Designer, as shown in Figure 8-5.

    Figure 8-5 Ruleset with Decision Table for the Car Rental Sample Application

    Description of Figure 8-5 follows
    Description of "Figure 8-5 Ruleset with Decision Table for the Car Rental Sample Application"

8.4.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 8-6.

Figure 8-6 Decision Function for Car Rental Sample with Decision Table Ruleset

Description of Figure 8-6 follows
Description of "Figure 8-6 Decision Function for Car Rental Sample with Decision Table Ruleset"

8.5 Creating a Java Application Using Rules SDK Decision Point

When you use Rules SDK in a development environment, you have the option of using Decision Point API with a pre-loaded dictionary. In a production environment you typically use the Decision Point API with the MDS repository signature and the dictionary is stored in MDS. For more information on using a Decision Point with, see What You Need to Know About Using Decision Point in a Production Environment.

The source code for Oracle Business Rules-specific samples and SOA samples are available online in the Oracle SOA Suite samples page.

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 8-1 provides a summary of the different versions of the car rental sample.

Table 8-1 Java Files in the Decision Point Sample CarRentalProject

Base Java Filename Description

CarRental

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.

8.5.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 below:

    static {
        try {
            // specifying the Decision Function and a pre-loaded
            // RuleDictionary instance 
            m_decisionPoint =  new DecisionPointBuilder()
                                .with(DF_NAME)
                                .with(loadRuleDictionary())
                                .build();
        } catch (SDKException e) {
            System.err.println("Failed to build Decision Point: " + e.getMessage());
            e.printStackTrace();
        }
    }

The above example 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().

This chain shown in example above includes the following steps:

  1. The first step is to create a DecisionPointBuilder instance with code such as the following:
    new DecisionPointBuilder()
    
  2. 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.

  3. Call only one of the other two with() methods. In this case the sample code uses a pre-loaded Rule Dictionary instance, containing the specified decision function. The loadDictionary() method loads an instance of RuleDictionary from a file. Example 8-1 shows the loadDictionary() method. For more information, see How to Use a Decision Point with a Pre-loaded Dictionary.
    .with(loadRuleDictionary())
    
  4. 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.

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

Example 8-1 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 8-1, 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.

Example 8-1 Load Rule Dictionary Method

private static RuleDictionary loadRuleDictionary(){ 
        RuleDictionary dict = null; 
        BufferedReader reader = null; 
        try { 
            reader = new BufferedReader( 
                        new InputStreamReader( 
                            new FileInputStream( 
                                new File(DICT_LOCATION)), "UTF-8")); 
            dict = RuleDictionary.readDictionary(reader, 
                                                 new 
DecisionPointDictionaryFinder(null)); 
 
            List<SDKWarning> warnings = new ArrayList<SDKWarning>(); 
 
            dict.update(warnings); 
            if (warnings.size() > 0) { 
                System.err.println("Validation warnings: " + warnings); 
            } 
        } catch (SDKException e){ 
            System.err.println(e); 
        } catch (FileNotFoundException e){ 
            System.err.println(e); 
        } catch (IOException e){ 
            System.err.println(e); 
        } finally { 
            if (reader != null) { try { reader.close(); } catch (IOException 
ioe) {ioe.printStackTrace();}} 
        } 
        return dict; 
    } 

8.5.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. The following code example 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.

        ExecutorService exec = Executors.newCachedThreadPool();
        List<Driver> drivers = createDrivers();
 
        for (int i = 0; i < NUM_CONCURRENT; i++) {
            Driver driver = drivers.get(i % drivers.size());
            exec.execute(new DriverCheckerRunnable(driver));
        }

The above example includes the following code for the sample application:

  • Create the Executor Service:

    ExecutorService exec = Executors.newCachedThreadPool();
    
  • Call method createDrivers(), defined in CarRental.java, to create a list of Driver instances.

    List<Driver> drivers = createDrivers();
    
  • A loop through a list of Driver instances to fill the driver list with drivers.

  • A loop to start multiple threads from DriverCheckerRunnable instances. These instances open a Decision Point and run the rules on each driver. For information on this code, see How to Create and Use Decision Point Instances.

The following code example shows the code that waits for the threads to complete.

        try {
            exec.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exec.shutdown();
    }

8.5.4 How to Create and Use Decision Point Instances

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

Example 8-2 shows the following:

  • Getting a DecisionPointInstance from the static DecisionPoint defined with the DecisionPointBuilder, with the following code.

     DecisionPointInstance instance = m_decisionPoint.getInstance();
    
  • Add inputs according to the signature of the decision function associated with the Decision Point. This defines one argument of type List as the input. This List contains the Driver instances:

                instance.setInputs(new ArrayList<Object>() {
                        {
                            add(driver);
                        }
                    });
    
  • Invoke the Decision Point and store the return value. The return type follows the same pattern as the decision function which is being called in the Decision Point.

     List<Object> outputs = instance.invoke();
    

    In this case the invoke() returns a List of length one, containing a List of Denial instances.

  • If the return is a List of any other size than one, then this is an error:

    if (outputs.isEmpty())
      System.err.println("Oops, no results");
    
  • The first entry that is returned from the Decision Point is cast to a List of type List<Denial>:

                java.util.List<Denial> denials =
                    (java.util.List<Denial>)outputs.get(0);
    
  • 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:

                if (denials.isEmpty()) {
                    System.out.println("Rental is allowed for " +
                                       driver.getName());
                } else {
                    for (Denial denial : denials) {
                        System.out.println("Rental is denied for " +
                                           denial.getDriver().getName() +
                                           " because " + denial.getReason());
                    }
                }
    

8.5.4.1 Sample Code to Create a Decision Point Instance with getInstance()

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

Example 8-2 Code to Create a Decision Point Instance with getInstance()

public class CarRentalWithDecisionPoint extends CarRental {
 
    protected static DecisionPoint m_decisionPoint;
    
    public static void checkDriver(final Driver driver) {
        try {
            DecisionPointInstance instance = m_decisionPoint.getInstance();
            instance.setInputs(new ArrayList<Object>() {
                    {
                        add(driver);
                    }
                });
            List<Object> outputs = instance.invoke();
 
            if (outputs.isEmpty())
                System.err.println("Oops, no results");
 
            java.util.List<Denial> denials =
                (java.util.List<Denial>)outputs.get(0);
            if (denials.isEmpty()) {
                System.out.println("Rental is allowed for " +
                                   driver.getName());
            } else {
                for (Denial denial : denials) {
                    System.out.println("Rental is denied for " +
                                       denial.getDriver().getName() +
                                       " because " + denial.getReason());
                }
            }
        } catch (RLException e) {
            e.printStackTrace();
        } catch (SDKException e) {
            e.printStackTrace();
        }
    }
    
}

8.6 Running the Car Rental Sample

In the car rental sample installed on your system, for the code shown in Example 8-1, modify the value of DICT_LOCATION to match the location of the dictionary on your system.

To run the car rental sample on your system:

  1. In the Application Navigator, select the dictionary and from the Edit menu select Copy Path.
  2. In the CarRental.java file, paste the path value into the DICT_LOCATION value.
  3. In the CarRentalProject select the CarRentalWithDecisionPointUsingPreloadedDictionary.java file.
  4. Right-click and in the list select Run.

8.6.1 Sample Output from Car Rental

Example 8-3 shows sample output from car rental application.

Example 8-3 Output from Car Rental Sample

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

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

In a production environment you can use an MDS repository to store Oracle Business Rules dictionaries. When you use an MDS repository to store the dictionary, the steps shown in How to Add a Decision Point Using Decision Point Builder and How to Use a Decision Point with a Pre-loaded Dictionary change to access the dictionary. The CarRentalWithDecisionPointUsingMdsRepository shows sample code for using Decision Point with MDS.

To see a complete example with deployment steps showing the use of a Decision Point to access a dictionary in MDS, see Adding a Servlet with Rules SDK Calls for Grades Sample Application.

The following code example 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.

    static {
        try {
            // specifying the Decision Function and Dictionary FQN
            // loads the rules from the MDS repository.
            m_decisionPoint = new DecisionPointBuilder()
                                .with(DF_NAME)
                                .with(DICT_FQN)
                                .build();
        } catch (SDKException e) {
            System.err.println("Failed to build Decision Point: " +
                               e.getMessage());

Similar to the steps in section How to Add a Decision Point Using Decision Point Builder, the above example shows the following:

  1. The first step is to create a DecisionPointBuilder instance with.

    new DecisionPointBuilder()
    
  2. 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.

  3. Call only one of the other two with() methods. In this case the sample code calls a DictionaryFQN to access an MDS repository. The code example in step 4 shows the routing that uses the dictionary package and the dictionary name to create the DictionaryFQN.

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

    protected static final String DICT_PKG = "com.example.rules.demo";
    protected static final String DICT_NAME = "CarRental";
    
    protected static final DictionaryFQN DICT_FQN =
        new DictionaryFQN(DICT_PKG, DICT_NAME);
    protected static final String DF_NAME = "CarRentalDecisionFunction";

8.8 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:

RuleDictionary dict = ...;
DecisionTrace trace = ...;
dict.processDecisionTrace(trace);

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.

Table 8-2 shows the Decision Point API methods for setting decision trace options.

Table 8-2 Decision Point Decision Tracing Methods

Method Description

decisionTrace

Get the decision trace produced from the call to invoke.

Returns DecisionTrace

getDecisionTraceLevel

Get the decision trace level to be used by the RuleSession. This value defaults to DECISION_TRACE_OFF, which means no trace information is gathered. Possible values are: DECISION_TRACE_OFF

DECISION_TRACE_DEVELOPMENT

DECISION_TRACE_PRODUCTION

Return Type: String

getDecisionTraceLimit

Get the decision trace limit, or maximum number of trace elements which are retrieved for the trace.

Return Type: int

setDecisionTraceLevel

Set the decision trace level to be used by the RuleSession. This parameter value is a String. Possible values are: DECISION_TRACE_OFF

DECISION_TRACE_DEVELOPMENT

DECISION_TRACE_PRODUCTION

setDecisionTraceLimit

Set the decision trace limit, or maximum number of trace elements which are retrieved for the trace.

8.8.1 Sample Usage of Decision Tracing

Example 8-4 shows sample usage of decision tracing with DecisionPoint API.

For more information on decision tracing, see Tracing Rule Execution in Fusion Middleware Control Console in Administering Oracle SOA Suite and Oracle Business Process Management Suite.

Example 8-4 Using Decision Trace from Decision Point API

DecisionPoint dp = new DecisionPointBuilder()
  .with(new DictionaryFQN("com.foo", "Bar"))
  .with("MyDecisionFunction")
  .setDecisionTraceLevel(DecisionPointBuilder.DECISION_TRACE_DEVELOPMENT)
  .setDecisionTraceLimit(24000)
  .build();
 
...
 
DecisionPointInstance dpi = dp.getInstance();
 
dpi.invoke();
 
DecisionTrace trace = dpi.decisionTrace();