Oracle® Fusion Middleware User's Guide for Oracle Business Rules 11g Release 1 (11.1.1) E10228-03 |
|
![]() Previous |
![]() Next |
Oracle Business Rules allows you to use Oracle ADF Business Components view objects as facts. By using ADF Business Components facts you can assert trees of view object graphs representing the business objects upon which rules should be based, and let Oracle Business Rules handle the complexities of managing the relationships between the various related view objects in the main view object's tree.
This chapter includes the following sections:
Section 10.1, "Introduction to Using Business Rules with ADF Business Components"
Section 10.2, "Using Decision Points with ADF Business Components Facts"
Section 10.3, "Creating a Business Rules Application with ADF Business Components Facts"
The ADF Business Components rule development process can be summarized as follows:
Create view object definitions.
Create action types.
Create rule dictionary.
Register view object fact types.
Register Java fact types for actions.
If you are invoking from Java:
If the view object is already instantiated at the Decision Point, code the Decision Point invocation passing the view object instance.
If the view object is not instantiated at the Decision Point, code the Decision Point invocation passing the view object key values.
When an ADF Business Components view object is imported into an Oracle Business Rules data model, an ADF Business Components fact type is created which has a property corresponding to each attribute of the view object, as shown in Figure 10-1.
Additionally, the ADF Business Components fact type contains the following:
A property named ViewRowImpl which points directly to the oracle.jbo.Row
instance that each fact instance represents.
A property named key_values which points to an oracle.rules.sdk2.decisionpoint.KeyChain
object. You can use this property to retrieve the set of key-values for this row and its parent rows.
Figure 10-1 ADF Business Components Sample Fact Type
Note the following:
Relationships between view object definitions are determined by introspection of attributes on the View Definition, specifically, those attributes which are View Link Accessors.
The ADF Business Components fact type importer correctly determines which relationships are 1-to-1 and which are 1-to-many and generates definitions in the dictionary accordingly. For 1-to-many relationships the type of the property generated is a List
which contains facts of the indicated type at runtime.
ADF Business Components fact types are not Java fact types and do not allow invoking methods on any explicitly created implementation classes for the view object.
If you need to call such methods then add the view object implementation to the dictionary as a Java fact type instead of as an ADF Business Components fact type. In this case, all getters and setters and other methods become available but the trade-off is that related view objects become inaccessible and, should related view object access be required, these relationships must be explicitly managed.
Internally in Oracle Business Rules, when you use ADF Business Components fact types these fact types are created as instances of RL fact types. Thus, you cannot assert ADF Business Components view object instances directly to a Rule Session, but must instead use the helper methods provided in the MetadataHelper
and ADFBCFactTypeHelper
classes. For more information, see Oracle Fusion Middleware Java API Reference for Oracle Business Rules.
With Rules SDK, the primary way to update a view object within a Decision Point is with an action type. An action type is a Java class that you import into the rule dictionary data model in the same way you import a rule pattern fact type Java class. A new instance of this action type is then asserted in the action of a rule and then processed by the Postprocessing Ruleset in the DecisionPointDictionary
.
A Java class to be used as an action type must conform to the following requirements:
The Java fact type class must subclass oracle.rules.sdk2.decisionpoint.ActionType
or oracle.rules.sdk2.decisionpoint.KeyedActionType
.
By subclassing KeyedActionType
the Java class inherits a standard oracle.rules.sdk2.decisionpoint.KeyChain
attribute, which may be used to communicate the rule fact's primary keys and parent-keys to the ActionType
instance.
The class has a default constructor.
The class implements abstract exec
method for the ActionType
. The exec
method should contain the main action which you want to perform.
The Java class must have properties which conform to the JavaBean
interface (that is, each property must have a getter and setter method).
Example 10-1 shows a sample ActionType
implementation.
Example 10-1 Implementing an ActionType
package com.example; import oracle.jbo.domain.Number; import oracle.rules.sdk2.decisionpoint.ActionType; import oracle.rules.sdk2.decisionpoint.DecisionPointInstance; public class RaiseAction extends ActionType { private double raisePercent; public void exec(DecisionPointInstance dpi) { Number salary = (Number)getViewRowImpl().getAttribute("Salary"); salary = (Number)salary.multiply(1.0d + getRaisePercent()).scale(100,2, new boolean[]{false}); dpi.addResult("raise for " + this.getViewRowImpl().getAttribute("EmployeeId"), getRaisePercent() + "=>" + salary ); getViewRowImpl().setAttribute("Salary", salary); } public void setRaisePercent(double raisePercent) { this.raisePercent = raisePercent; } public double getRaisePercent() { return raisePercent; } }
In Example 10-1, there is an oracle.rules.sdk2.decisionpoint.DecisionPointInstance
as a parameter to the exec
method. Table 10-1 shows the methods in DecisionPointInstance
that an application developer might need when implementing the ActionType
exec
.
Table 10-1 DecisionPointInstance Methods
Method | Description |
---|---|
|
Supplies a If you intend to use the decision function from a Decision service, use only String values. |
|
Gives access to the Oracle Business Rules RuleSession object from which static configuration variables in the Rule Dictionary may be accessed. |
|
If populated by the caller, supplies a String value to be used for Set Control indirection. |
|
Provides a transaction object so that action types may make persistent changes in the back end. |
|
Adds a named result to the list of output values in the form of a String key and Object value. Output is assembled as a |
Using Rules Designer you can select parameters appropriate for the ActionType
you are configuring.
You can use a Decision Point to execute a decision function. There are certain Decision Point methods that only apply when working with ADF Business Components Fact types. For more information on decision functions, see Chapter 6, "Working with Decision Functions".
When you use ADF Business Components fact types you invoke a decision function using the Rules SDK Decision Point interface.
To call a decision function using the Rules SDK Decision Point interface:
Construct and configure the template DecisionPoint
instance using the DecisionPointBuilder
.
For more information, see Section 7.3.1, "How to Add a Decision Point Using Decision Point Builder".
Create a DecisionPointInstance
using the DecisionPoint
method getInstance
.
Add the fact objects you want to use to the DecisionPointInstance
using DecisionPointInstance
method addInput
, setInputs
, or setViewObject
. These are either ViewObject
or ViewObjectReference
instances. These must be added in the same order as they are declared in the decision function input. For more information, see Section 10.2.1.3, "Calling the Invoke Method for an ADF Business Components Rule"
Set the transaction to be used by the DecisionPointInstance
.
For more information, see Section 10.2.1.1, "Setting the Decision Point Transaction".
Set any runtime properties the consequent application actions may expect.
For more information, see Section 10.2.1.2, "Setting Runtime Properties".
Call the DecisionPointInstance
method invoke
.
For more information, see:
The Oracle Business Rules SDK framework requires an oracle.jbo.server.DBTransactionImpl2
instance to load a ViewObject
and to provide ActionType
instances within a transactional context. The class oracle.jbo.server.DBTransactionImpl2
is the default JBO transaction object returned by calling the ApplicationModule
method getTransaction
. Setting the transaction requires calling the DecisionPointInstance
method setTransaction
with the Transaction
object as a parameter.
Should a DBTransaction
instance not be available for some reason, the Oracle Business Rules SDK framework can bootstrap one using any of the three provided overrides of the setTransaction
method.
These require one of:
A JDBC URL, user name, and password.
A JDBC connection object.
A javax.sql.DataSource
object and a flag to specify whether the DataSource
represents a JTA transaction or a local transaction.
Runtime properties may be provided with the setProperty
method. These can then be retrieved by ActionType
instances during their execution. If no runtime properties are needed, you may safely omit these calls.
The ViewObject
to be used in a Decision Point invocation can be specified in one of two ways, as shown in Table 10-2.
Table 10-2 Setting the View Object for a Decision Point Invocation
ViewObject Set Method | Description |
---|---|
|
The decision function is invoked once for each Section 10.3.9.3, "How to Add Retract Employees Ruleset" shows this usage. To use |
|
The decision function is invoked once with all of the |
Example 10-2 shows how to invoke a Decision Point with a ViewObject
instance using the setInputs
method. For the complete example, see Example 10-5.
Example 10-2 Invoking a Decision Point Using setInputs Method
public class OutsideManagerFinder { private static final String AM_DEF = "com.example.AppModule"; private static final String CONFIG = "AppModuleLocal"; private static final String VO_NAME = "EmployeesView1"; private static final DictionaryFQN DICT_FQN = new DictionaryFQN("com.example", "Chapter10Rules"); private static final String DF_NAME = "FindOutsideManagers"; private DecisionPoint dp = null; public OutsideManagerFinder() { try { dp = new DecisionPointBuilder() .with(DICT_FQN) .with(DF_NAME) .build(); } catch (SDKException e) { System.err.println(e); } } public void run() { final ApplicationModule am = Configuration.createRootApplicationModule(AM_DEF, CONFIG); final ViewObject vo = am.findViewObject(VO_NAME); final DecisionPointInstance point = dp.getInstance(); point.setTransaction((DBTransactionImpl2)am.getTransaction()); point.setAutoCommit(true); point.setInputs(new ArrayList<Object>(){{ add(vo); }}); try { List<Object> invokeList = point.invoke(); List<DecisionPoint.NamedValue> results = point.getResults(); } catch (RLException e) { System.err.println(e); } catch (SDKException e) { System.err.println(e); } }
Example 10-3 shows how to invoke a DecisionPoint
using the setViewObject
method to set the ViewObject
.
Example 10-3 Invoking a Decision Point Using setViewObject Method
public void run() { final ApplicationModule am = Configuration.createRootApplicationModule(AM_DEF, CONFIG); final ViewObject vo = am.findViewObject(VO_NAME); final DecisionPointInstance point = dp.getInstance(); point.setTransaction((DBTransactionImpl2)am.getTransaction()); point.setAutoCommit(true); point.setViewObject(vo); try { List<Object> invokeList = point.invoke(); List<DecisionPoint.NamedValue> results = point.getResults(); } catch (RLException e) { System.err.println(e); } catch (SDKException e) { System.err.println(e); } }
Care must be taken when invoking Decision Points using a view object that loads large amounts of data, since the default behavior of the JBO classes is to load all data eagerly. If a view object with many rows and potentially very many child rows is loaded into memory, not only is there risk of memory-exhaustion, but DML actions taken based on such large data risk using all rollback segments.
To call a decision function with a ruleset using ADF Business Components fact types with the Oracle Business Rules SDK Decision Point interface you must configure the decision function with certain options. For more information on using decision functions, see Chapter 6, "Working with Decision Functions".
To define a decision function using the Java Decision Point interface:
Double-click the decision function icon to the left of the decision function item or select this item and click the Edit icon. The Edit Decision Function dialog appears.
In the Edit Decision Function dialog, configure the decision function:
Input Fact Types: names the fact types to use in the configured business rules.
The inputs, when working with an application using ADF Business Components fact types, are the ADF Business Components view objects used in your rules.
When you use the setViewObject
method with a Decision Point, the List attribute should be unselected. Each Input fact type should have the List attribute selected when you are using addInput
or setInputs
methods with the Decision Point. Optionally, depending on the usage of the view objects, select the Tree attribute:
List: defines that a list of ADF Business Components fact types are passed to the decision function.
Tree: defines that all objects in the master-detail hierarchy should be asserted, instead of only the top-level object.
For more information, see Section 10.2.1, "How to Call a Decision Point with ADF Business Components Facts".
Output Fact Types: defines the fact types that the caller returns.
When calling a decision function using the Java Decision Point interface for a decision function that uses ADF Business Components fact types, Output Fact Types should be left empty. The view object is updated using an ActionType
. For more information, see Section 10.1.2, "Understanding Oracle Business Rules Decision Point Action Type".
RuleSets and Decision Functions: an ordered list of the rulesets and other decision functions that this decision function executes. The rulesets DecisionPointDictionary.Preprocessing and DecisionPointDictionary.Postprocessing from the DecisionPoint dictionary must be added so that they run before and after, respectively, the application-specific rulesets and decision functions.
Both rulesets and decision functions may be included in the definition of a decision function. It is common for an application to require some rules or decision functions which act as "plumbing code". Such applications include components that perform transformations on the input data, assert auxiliary facts, or process output facts. The plumbing code may need to run before or after the rules that contain the core business rules of the application. You can separate these application concerns and their associated rules from the application functional concerns using nested decision functions. Using nested decision functions, the inner decision function does not contain the administrative, plumbing-oriented concerns, and thus only presents those rules which define the core logic of the application. This design eliminates the need for the user to understand the administrative rules and prevents a user from inappropriately modifying these rules (and possibly rendering the system inoperable due to these changes).
To create a configuration using multiple rulesets and nested decision functions, create two decision functions and add one to the other. A good naming scheme is to suffix the nested inner decision function with the name Core
. The user specified rulesets can be added to the inner Core
decision function. For example, DecisionFunction_1 can be defined to run the DecisionPointDictionary.Preprocessing decision function, the DecisionFunction_1Core decision function, and the DecisionPointDictionary.Postprocessing decision function. For this example, DecisionFunction_1Core contains the core business logic rulesets.
It is also common for the input of a Decision Point to be an ADF Business Components fact type that is the root of a tree of ADF Business Components objects. However, the user might only write business rules that match on a subset of the types found in the tree. In this case, it is a good practice to define the inputs of the nested decision functions to be only the types which are actually matched in the contained rulesets. For example, consider a Decision Point calling a decision function whose input is an Employee
fact type with the Tree option selected; if this decision function includes a nested decision function with rulesets that only matched on the Department
fact type. In this case, the nested decision function could either have as its input specified as an Employee
fact type with the Tree option selected, or a Department
fact type with the List option selected. For this example, the Tree option causes the children of the Employee
instances, including the Department
instances to be asserted (due to the one-to-many relationship between these types). If Employee
is an input to the outer decision function and the Tree option is selected, the then Department
fact type instances are asserted, and you can identify the signature on the inner decision function as a list of Department
instances (these are the exact types which are being matched on for this decision function).
The ADF Business Components sample application shows the use of ADF Business Component fact types.
The source code for Oracle Business Rules-specific samples is available online at
http://www.oracle.com/technology/sample_code/products/rules
For SOA samples online visit
http://www.oracle.com/technology/sample_code/products/soa
To work with Oracle Business Rules with ADF Business Components facts, you first need to create an application and a project in Oracle JDeveloper.
To create an application that uses ADF Business Components facts:
Start Oracle JDeveloper. This displays the Oracle JDeveloper start page.
In the Application Navigator, in the application menu click New Application....
In the Name your application page enter the name and location for the new application:
In the Application Name field, enter an application name. For example, enter Chapter10
.
In the Directory field, enter or browse for a directory name or accept the default.
In the Application Package Prefix field, enter an application package prefix. For example, enter com.example
.
This should be a globally unique prefix and is commonly a domain name owned by your company. The prefix, followed by a period, applies to objects created in the initial project of an application.
In this sample, use the prefix com.example
.
In the Application Template field, select Fusion Web Application (ADF).
Click Finish.
You need to add a new project named Chapter10.
Add a new project:
In the Chapter10 application, select the Application Menu.
In the Application Menu list, select New Project....
In the New Gallery, in the Items area select Generic Project.
Click OK.
On the Name your project page, in the Project Name field enter Chapter10
.
Click Finish.
You need to add ADF Business Components from a database table. For this example we use the standard HR database tables.
To add ADF Business Components:
In the Application Navigator, select the Chapter10 project.
Right-click and from the menu select New....
In the New Gallery, in the Categories area expand Business Tier and select ADF Business Components.
In the Items area select Business Components from Tables.
Click OK.
In the Initialize Business Components Project dialog, enter the required connection information to add a connection.
Click OK. This displays the Create Business Components from Tables wizard.
In the Entity Objects page, select the desired objects by moving objects from the Available box to the Selected box. You may need to click Query to see the complete list. For example, select DEPARTMENTS and EMPLOYEES, as shown in Figure 10-2.
Figure 10-2 Selecting Entity Objects for Sample Application
Click Next. This displays the Updatable View Objects page.
In the Updatable View Objects page select Departments and Employees, as shown in Figure 10-3.
Figure 10-3 Adding Updatable View Objects for Sample Application
Click Next. This displays the Read-Only View Objects page.
Click Next. This displays the Application Module page.
Click Finish.
You should tune the ViewObject
to meet the performance requirements of your application.
To set tuning options for EmployeesView:
In the Application Navigator, double-click EmployeesView.
In the General navigation tab, expand Tuning.
In the Tuning area, select All Rows.
In the Tuning area, in the Batches of: field, enter 128.
In the Tuning area, select All at Once.
To set tuning options for DepartmentsView:
In the Application Navigator, double-click DepartmentsView.
In the General navigation tab, expand Tuning.
In the Tuning area, select All Rows.
In the Tuning area, in the Batches of: field, enter 128.
In the Tuning area, select All at Once.
You use Oracle JDeveloper to create an Oracle Business Rules dictionary.
To create a dictionary:
In the Application Navigator, select the Chapter10 project.
Right-click, and from the list select New....
In the New Gallery, select the All Technologies tab and in the Categories area expand Business Tier and select Business Rules.
In the New Gallery, in the Items area select Business Rules.
Click OK.
In the Create Business Rules dialog enter the dictionary name and package, as shown in Figure 10-4:
For example, in the Name field enter Chapter10Rules
.
For example, in the Package field enter com.example
.
Figure 10-4 Create Business Rules for Chapter10Rules Dictionary
Click OK.
JDeveloper creates the dictionary and opens the Chapter10Rules.rule
s file in Rules Designer, as shown in Figure 10-5.
You need to add a dictionary links to the Oracle Business Rules supplied Decision Point Dictionary. This dictionary supports features for working with the Decision Point interface with ADF Business Components objects.
Add decision point dictionary links:
In the Rules Designer, click the Links navigation tab.
From the menu next to the Create icon, select Decision Point Dictionary. This operation can take awhile to complete. After waiting, Rules Designer adds a link to the Decision Point Dictionary as shown in Figure 10-6.
Figure 10-6 Adding a Dictionary Link to Decision Point Dictionary
You import ADF Business Components facts with Rules Designer to make these objects available when you create rules.
Import the ADF Business Components facts:
In Rules Designer, select the Facts navigation tab.
Select the ADF-BC Facts tab.
Click the Create... icon. This displays the ADF Business Components Fact page.
In the Connection field, from the list select the connection which your ADF Business Components objects use. The Search Classpath area shows a list of classpaths.
In the View Definition field, select the name of the view object to import. For example, select com.example.EmployeesView.
Click OK. This displays the Facts navigation tab, as shown in Figure 10-7.
Figure 10-7 ADF Business Components Facts in Rules Designer
ADF Business Components Facts can include a circular reference, as indicated with the validation warning:
RUL-05037: A circular definition exists in the data model
When this warning is shown in the Business Rule validation log, you need to manually resolve the circular reference. To do this you deselect the Visible checkbox for one of the properties that is involved in the circular reference.
To mark a property as non-visible:
Select the Facts navigation tab and select the ADF Business Components Facts tab.
Double-click the icon in the DepartmentsView row.
In the Properties table, in the EmployeesView row deselect the Visible checkbox.
Click OK.
To set alias for DepartmentsView and EmployeesView:
Select the Facts navigation tab and select the ADF Business Components Facts tab.
In the Alias column, replace EmployeesView with Employee.
In the Alias column, replace DepartmentsView with Department.
The sample code that runs the outside manager ruleset invokes the Decision Point with the view object set using the setInputs
method. This invokes the decision function once, with all of the view object rows loaded in a List
. Note that invoking the Decision Point this way is not scalable, because all of the view object rows must be loaded into memory at the same time, which can lead to OutOfMemory exceptions. Only use this invocation style when there are a small and known number of view object rows. You can also use a Decision Point with setViewObject
. For more information, see Section 10.2.1, "How to Call a Decision Point with ADF Business Components Facts".
After the view objects are imported as facts, you can rename the ruleset and create the decision function for the application.
To rename the ruleset:
In Rules Designer, select the Ruleset_1 navigation tab.
Select the ruleset name and enter Outside Manager Ruleset
to rename the ruleset.
To add a decision function:
Click the Decision Functions navigation tab.
In the Decision Functions area, click Create.... This displays the Edit Decision Function dialog.
Edit the decision function fields as follows, as shown in Figure 10-8.
Enter Name value FindOutsideManagers
.
In the Inputs area, click the Add Input icon and edit the input information as follows:
Click the Fact Type field and select Employee from the list.
Select the List checkbox.
In this decision function you do not define any outputs because you use the ActionType
API for taking action rather than producing output. For more information, see Section 10.1.2, "Understanding Oracle Business Rules Decision Point Action Type".
In the Rulesets & Decision Functions area move the following items from the Available area to the Selected area, in the specified order:
DecisionPointDictionary.Preprocessing
Outside Manager Ruleset
DecisionPointDictionary.Postprocessing
Figure 10-8 Adding the Find Outside Managers Decision Function
Ensure that the items in the Selected area are in the order shown in Figure 10-8.
If they are not, select an item and use the Move Up and Move Down buttons to correct the order.
Click OK.
Several warnings appear. These warnings are removed in later steps when you add rules to the ruleset.
To create the sample application and to modify the view object in a rule, you need to create a Java implementation class for abstract class oracle.rules.sdk2.decisionpoint.ActionType
. All subclasses of ActionType
must implement the abstract exec
method.
To create the ActionType Java implementation class:
In Oracle JDeveloper, select the project named Chapter10.
In the Application Navigator, select the Application Sources folder.
Right-click and from the list select New....
In the New Gallery, in the Categories area select General.
In the New Gallery, in the Items area select Java Class.
Click OK.
In the Create Java Class dialog, configure the following properties as shown in Figure 10-9:
Enter the Name value MessageAction
.
Enter the Package value com.example
.
Enter the Extends value oracle.rules.sdk2.decisionpoint.ActionType
.
Figure 10-9 Creating the Message Action Type Java Class
Click OK.
Oracle JDeveloper displays the Java Class.
Replace this code with the code shown in Example 10-4.
Example 10-4 ActionType Java Implementation
package com.example; import oracle.rules.sdk2.decisionpoint.ActionType; import oracle.rules.sdk2.decisionpoint.DecisionPointInstance; public class MessageAction extends ActionType { public MessageAction() { super(); } public void exec(DecisionPointInstance decisionPointInstance) { System.out.println(message); } private String message = null; public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } }
In the Application Navigator, right click the MessageAction.java
and from the list select Make.
You just created a new Java class and you need to add this class as a Java fact type in Rules Designer to use later when you create rules.
To create the Java fact type:
In Rules Designer, click the Facts navigation tab.
Select the Java Facts tab.
Click Create....
In the Create Java Fact dialog, in the Classes area navigate in the tree and expand com
and example
to display the MessageAction checkbox.
Select the MessageAction checkbox, as shown in Figure 10-10.
Figure 10-10 Create Java Fact with Message Action Type
Click OK.
This adds the fact to the table, as shown in Figure 10-11.
Figure 10-11 Adding the Message Action Type Java Fact
You add the rule to find the managers that are in a different departments than their employees.
To add the find managers in different departments rule:
In Rules Designer, select the Outside Manager Ruleset tab.
Click Add and from the list select Create Rule.
Rename the rule by selecting the default rule name Rule_1. This displays a text entry area. You enter a name. For example, enter Find managers in different department. Press Enter to apply the name.
Click Show Advanced Settings. For more information, see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table".
In the rule select Advanced Mode, as shown in Figure 10-12.
Figure 10-12 Adding the Find Managers in Different Departments Rule
Enter the rule as shown in Figure 10-13. The action for the rule shown in the THEN area is too long to show in the figure. The complete action that you build includes the following items:
"Employee " + Employee.FirstName + " " + Employee.LastName + "(" + Employee.EmployeeId + ")"+ " in dept " + Employee.DepartmentId + " has manager outside of department, " + Manager.FirstName + " " + Manager.LastName + "(" + Manager.EmployeeId + ")" + " in dept " + Manager.DepartmentId
Figure 10-13 Find Managers in Different Departments Rule
Add the outside manager finder class. This uses the Decision Point to execute a decision function.
To add the Outside Manager Finder Class:
Select the Chapter10 project.
Right-click and select New....
In the New Gallery, in the Categories area select General.
In the New Gallery, in the Items area select Java Class.
Click OK.
In the Name field, enter OutsideManagerFinder
.
Click OK.
Replace the contents of this class with the code shown in Example 10-5.
Example 10-5 Outside Manager Finder Java Class with Decision Point
package com.example; import java.util.ArrayList; import oracle.jbo.ApplicationModule; import oracle.jbo.ViewObject; import oracle.jbo.client.Configuration; import oracle.rules.rl.exceptions.RLException; import oracle.rules.sdk2.decisionpoint.DecisionPoint; import oracle.rules.sdk2.decisionpoint.DecisionPointBuilder; import oracle.rules.sdk2.decisionpoint.DecisionPointInstance; import oracle.rules.sdk2.exception.SDKException; import oracle.rules.sdk2.repository.DictionaryFQN; public class OutsideManagerFinder { private static final String AM_DEF = "com.example.AppModule"; private static final String CONFIG = "AppModuleLocal"; private static final String VO_NAME = "EmployeesView1"; private static final DictionaryFQN DICT_FQN = new DictionaryFQN("com.example", "Chapter10Rules"); private static final String DF_NAME = "FindOutsideManagers"; private DecisionPoint dp = null; public OutsideManagerFinder() { try { dp = new DecisionPointBuilder() .with(DICT_FQN) .with(DF_NAME) .build(); } catch (SDKException e) { System.err.println(e); } } public void run() { final ApplicationModule am = Configuration.createRootApplicationModule(AM_DEF, CONFIG); final ViewObject vo = am.findViewObject(VO_NAME); final DecisionPointInstance point = dp.getInstance(); point.setInputs(new ArrayList<Object>(){{ add(vo); }}); try { point.invoke(); } catch (RLException e) { System.err.println(e); } catch (SDKException e) { System.err.println(e); } } public static void main(String[] args) { OutsideManagerFinder omf = new OutsideManagerFinder(); omf.run(); } }
You need to update the ADF-META-INF
file with MDS information for accessing the dictionary. You can use a local file with MDS to access the Oracle Business Rules dictionary. However, this procedure is not the usual dictionary access method with Oracle Business Rules in a production environment. For information on using a Decision Point to access a dictionary with MDS in a production environment, see Section 7.5, "What You Need to Know About Using Decision Point in a Production Environment".
Update ADF-META-INF:
In the Application Navigator, expand Application Resources.
Expand Descriptors and ADF META-INF folders.
Double-click adf-config.xml to open this file.
Click the Source tab to view the adf-config.xml
source.
Add the MDS information to adf-config.xml
, before the closing </adf-config>
tag, as shown in Example 10-6.
Example 10-6 Adding MDS Elements to adf-config.xml for Local Dictionary Access
<adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config">
<mds-config version="11.1.1.000" xmlns="http://xmlns.oracle.com/mds/config">
<persistence-config>
<metadata-namespaces>
<namespace metadata-store-usage="mstore-usage_1" path="/"/>
</metadata-namespaces>
<metadata-store-usages>
<metadata-store-usage id="mstore-usage_1">
<metadata-store class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
<property name="metadata-path"
value="C:\jdevinstance\mywork\Chapter10\.adf\"/>
</metadata-store>
</metadata-store-usage>
</metadata-store-usages>
</persistence-config>
</mds-config>
</adf-mds-config>
In the <property>
element with the attribute metadata-path
, change the path to match .adf
directory in the application on your system.
Copy definitions to MDS accessible location:
In a file system navigator, outside of Oracle JDeveloper navigate to the Chapter10 application, and in the Chapter10 project, in the src folder select and copy the com folder.
In the application directory for Chapter10, above the Chapter10 project, navigate to the .adf directory.
Copy the com folder to this directory.
Copy dictionary to MDS accessible location:
In a file system navigator, outside of Oracle JDeveloper navigate to the Chapter10 application and in the Chapter10 project, copy the oracle directory that contains the Oracle Business Rules dictionary.
In the application directory for Chapter10, above the Chapter10 project, navigate to the .adf directory.
Copy the oracle folder to this directory.
You can build and test the project by running the find managers with employees in different departments rule.
Build the OutsideManagerFinder configuration:
From the menu next to Run icon, select Manage Run Configurations....
In the Project Properties dialog, click New....
In the Create Run Configuration dialog, enter a name. For example, enter OutsideManagerFinder
.
Click OK.
With OutsideManagerFinder selected, click Edit....
In the Default Run Target field, click Browse....
Select OutsideManagerFinder.java from the src\com\example
folder.
Click Open.
In the Edit Run Configuration dialog, click OK.
In the Project Properties dialog, click OK.
Run the project:
In the menu next to the Run project icon, select OutsideManagerFinder.
Running this configuration generates output, as shown in Example 10-7.
Example 10-7 Running the OutsideManagerFinder Ruleset
Emp Shelley Higgins(205) in dept 110 manager outside of department, Neena Kochhar(101) in dept 90 Emp Hermann Baer(204) in dept 70 manager outside of department, Neena Kochhar(101) in dept 90 Emp Susan Mavris(203) in dept 40 manager outside of department, Neena Kochhar(101) in dept 90 Emp Michael Hartstein(201) in dept 20 manager outside of department, Steven King(100) in dept 90 Emp Jennifer Whalen(200) in dept 10 manager outside of department, Neena Kochhar(101) in dept 90 Emp Kimberely Grant(178) in dept null manager outside of department, Eleni Zlotkey(149) in dept 80 Emp Eleni Zlotkey(149) in dept 80 manager outside of department, Steven King(100) in dept 90 Emp Gerald Cambrault(148) in dept 80 manager outside of department, Steven King(100) in dept 90 Emp Alberto Errazuriz(147) in dept 80 manager outside of department, Steven King(100) in dept 90 Emp Karen Partners(146) in dept 80 manager outside of department, Steven King(100) in dept 90 Emp John Russell(145) in dept 80 manager outside of department, Steven King(100) in dept 90 Emp Kevin Mourgos(124) in dept 50 manager outside of department, Steven King(100) in dept 90 Emp Shanta Vollman(123) in dept 50 manager outside of department, Steven King(100) in dept 90 Emp Payam Kaufling(122) in dept 50 manager outside of department, Steven King(100) in dept 90 Emp Adam Fripp(121) in dept 50 manager outside of department, Steven King(100) in dept 90 Emp Matthew Weiss(120) in dept 50 manager outside of department, Steven King(100) in dept 90 Emp Den Raphaely(114) in dept 30 manager outside of department, Steven King(100) in dept 90 Emp Nancy Greenberg(108) in dept 100 manager outside of department, Neena Kochhar(101) in dept 90 Emp Alexander Hunold(103) in dept 60 manager outside of department, Lex De Haan(102) in dept 90
The sample code that runs the department manager ruleset invokes the Decision Point with the view object set using the setViewObject
method. This invokes the decision function once for each row in the view object. All decision function calls occur in the same RuleSession. Between decision function calls, the RuleSession preserves all state from the previous decision function call. Thus, any objects asserted during the previous call remain in working memory for the next call unless they are explicitly retracted by rulesets that you supply. When the state is maintained, you can retract all facts or selectively retract facts between calls by running a ruleset with rules that use the retract action. This ruleset is run as part of the same decision function that you use with the Decision Point. The retract all employees ruleset demonstrates retracting these facts, as shown in Figure 10-15. For more information, see Section 10.2.1, "How to Call a Decision Point with ADF Business Components Facts".
You now add the department manager finder ruleset.
To add the department manager finder ruleset:
In Rules Designer, click Create Ruleset....
In the Create Ruleset dialog, in the Name field enter Department Manager Finder Ruleset
.
Click OK.
Next you add the Find rule to find department managers. This rule demonstrates the use of Tree Mode rules with Oracle ADF Business Components fact types.
Add department manager finder rule:
In Rules Designer select the Department Manager Finder Ruleset.
In the menu next to the Add icon, click Create Rule.
Change the rule name by selecting the name Rule_1, and entering Find
.
Click Show Advanced Settings. For more information, see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table".
In the rule, select Tree Mode.
Enter the Find rule tests and actions, as shown in Figure 10-14. The THEN area includes the assert that is too wide for the figure. The following shows the complete text of this rule, which is missing in Figure 10-14:
Employee.FirstName + " " + Employee.LastName + " is the manager of dept " + Employee/DepartmentsView.DepartmentName
Figure 10-14 Adding the Find Rule to the Department Manager Finder Ruleset
You add a ruleset to retract the employee fact type instances. This ensures that the Employee fact type is removed between invocations of the decision function.
To add the retract employee ruleset:
Add the Retract Employees Ruleset.
In the Retract Employees Ruleset, add a rule and name it Retract all employees, as shown in Figure 10-15.
Figure 10-15 Adding the Retract All Employees Rule
Now you create the decision function for the department manager finder ruleset. You use this decision function to execute the ruleset from a Decision Point.
To add a decision function for department manager finder ruleset:
Click the Decision Functions navigation tab.
In the Decision Functions area, click Create.... This displays the Edit Decision Function dialog.
Update the decision function fields as follows, as shown in Figure 10-16.
Enter Name value FindDepartmentManagers
.
In the Inputs area, click the Add Input and edit the input information as follows:
Click the Fact Type field and select Employee from the list.
Select the Tree checkbox.
In this decision function you do not define any outputs, because you use the ActionType
API for taking action rather than producing output.
In the Rulesets & Decision Functions area, move the following items from the Available area to the Selected area, in the specified order:
DecisionPointDictionary.Preprocessing
Department Manager Finder Ruleset
Retract Employees
DecisionPointDictionary.Postprocessing
Figure 10-16 Adding the Find Department Managers Decision Function
Ensure that the items in the Selected area are in the order shown in Figure 10-16.
If they are not, select an item and use the Move Up and Move Down buttons to correct the order.
Click OK.
Add the department manager finder class. This class include the code with the Decision Point that executes the decision function.
Add the department manager finder class:
In the Application Navigator, select the Chapter10 project.
Right-click and select New....
In the New Gallery, in the Categories area select General.
In the New Gallery, in the Items area, select Java Class.
Click OK.
In the Name field, enter DeptManagerFinder
.
Click OK.
Replace the contents of this class with the code shown in Example 10-8.
Example 10-8 Department Manager Finder Class
package com.example; import oracle.jbo.ApplicationModule; import oracle.jbo.ViewObject; import oracle.jbo.client.Configuration; import oracle.jbo.server.DBTransactionImpl2; import oracle.rules.rl.exceptions.RLException; import oracle.rules.sdk2.decisionpoint.DecisionPoint; import oracle.rules.sdk2.decisionpoint.DecisionPointBuilder; import oracle.rules.sdk2.decisionpoint.DecisionPointInstance; import oracle.rules.sdk2.exception.SDKException; import oracle.rules.sdk2.repository.DictionaryFQN; public class DeptManagerFinder { private static final String AM_DEF = "com.example.AppModule"; private static final String CONFIG = "AppModuleLocal"; private static final String VO_NAME = "EmployeesView1"; private static final String DF_NAME = "FindDepartmentManagers"; private static final DictionaryFQN DICT_FQN = new DictionaryFQN("com.example", "Chapter10Rules"); private DecisionPoint dp = null; public DeptManagerFinder() { try { dp = new DecisionPointBuilder() .with(DICT_FQN) .with(DF_NAME) .build(); } catch (SDKException e) { System.err.println(e); } } public void run() { final ApplicationModule am = Configuration.createRootApplicationModule(AM_DEF, CONFIG); final ViewObject vo = am.findViewObject(VO_NAME); final DecisionPointInstance point = dp.getInstance(); point.setTransaction((DBTransactionImpl2)am.getTransaction()); point.setAutoCommit(true); point.setViewObject(vo); try { point.invoke(); } catch (RLException e) { System.err.println(e); } catch (SDKException e) { System.err.println(e); } } public static void main(String[] args) { new DeptManagerFinder().run(); } }
Copy the updated dictionary to an MDS accessible location.
Copy dictionary to MDS accessible location:
In a file system navigator, outside of Oracle JDeveloper, navigate to the Chapter10 application, and project and copy the oracle directory that contains the dictionary.
In the application directory for Chapter10, above the Chapter10 project, navigate to the .adf
directory.
Copy the oracle folder to this directory.
You can build and test the project to execute the department manager finder ruleset.
Build the project:
From the menu next to Run icon, select Manage Run Configurations....
In the Project Properties dialog, click New....
In the Create Run Configuration dialog, enter the name. For example, enter DeptManagerFinder
.
In the Copy Settings From field, enter Default.
Click OK.
With DeptManagerFinder selected, click Edit....
In the Default Run Target field, click Browse....
Select DeptManagerFinder.java from the src\com\example
directory.
Click Open.
In the Edit Run Configuration dialog, click OK.
In the Project Properties dialog, click OK.
Run the project:
In the menu next to the Run project icon, select DeptManager Finder.
Running the decision point generates output, as shown in Example 10-9.
Example 10-9 Output from Department Manager Finder Ruleset
Michael Hartstein is the manager of dept Marketing John Russell is the manager of dept Sales Adam Fripp is the manager of dept Shipping Den Raphaely is the manager of dept Purchasing Alexander Hunold is the manager of dept IT Shelley Higgins is the manager of dept Accounting Hermann Baer is the manager of dept Public Relations Susan Mavris is the manager of dept Human Resources Jennifer Whalen is the manager of dept Administration Nancy Greenberg is the manager of dept Finance Steven King is the manager of dept Executive Shelley Higgins is the manager of dept Accounting Hermann Baer is the manager of dept Public Relations Susan Mavris is the manager of dept Human Resources Jennifer Whalen is the manager of dept Administration Nancy Greenberg is the manager of dept Finance Alexander Hunold is the manager of dept IT Alexander Hunold is the manager of dept IT Nancy Greenberg is the manager of dept Finance Den Raphaely is the manager of dept Purchasing Adam Fripp is the manager of dept Shipping John Russell is the manager of dept Sales Jennifer Whalen is the manager of dept Administration Michael Hartstein is the manager of dept Marketing Susan Mavris is the manager of dept Human Resources Hermann Baer is the manager of dept Public Relations Shelley Higgins is the manager of dept Accounting
When you see duplicate entries in the output, when working with tree mode rules in this example, the duplicate entries are due to multiple rule firings on the same data in a different part of the view object graph.
The sample code that runs the raises ruleset invokes the Decision Point by specifying the view object using the setViewObject
method. This invokes the decision function once for each row in the view object. The retract employees ruleset retracts all instances of Employee
asserted for each call, so that they do not remain in working memory between calls to the decision function. The action type shown in Example 10-10 shows how to change the ViewRowImpl
attribute values with a ActionType
. For more information, see Section 10.2.1, "How to Call a Decision Point with ADF Business Components Facts".
You now add the raises ruleset.
To add the raises ruleset:
In Rules Designer, click Create Ruleset....
In the Create Ruleset dialog, in the Name field enter Raises Ruleset
.
Click OK.
To create this part of the sample application and to modify the view object in the raises rule, you need to create a Java implementation class for the abstract class oracle.rules.sdk2.decisionpoint.ActionType
. All subclasses of ActionType
must implement the abstract exec
method.
To create the raise ActionType Java implementation class:
In Oracle JDeveloper, select the project named Chapter10.
In the Application Navigator, select the Application Sources folder.
Right-click and from the list select New....
In the New Gallery, in the Categories area select General.
In the New Gallery, in the Items area select Java Class.
Click OK.
In the Create Java Class dialog, configure the following properties as shown in Figure 10-17:
Enter the Name value RaiseAction
.
Enter the Package value com.example
.
Enter the Extends value oracle.rules.sdk2.decisionpoint.ActionType
.
Figure 10-17 Creating the Raise ActionType Java Class
Click OK.
Oracle JDeveloper displays the Java Class.
Replace this code with the code shown in Example 10-10.
Example 10-10 ActionType Java Implementation
package com.example; import oracle.jbo.domain.Number; import oracle.rules.sdk2.decisionpoint.ActionType; import oracle.rules.sdk2.decisionpoint.DecisionPointInstance; public class RaiseAction extends ActionType { private double raisePercent; public void exec(DecisionPointInstance dpi) { Number salary = (Number)getViewRowImpl().getAttribute("Salary"); salary = (Number)salary.multiply(1.0d + getRaisePercent()).scale(100,2, new boolean[]{false}); dpi.addResult("raise for " + this.getViewRowImpl().getAttribute("EmployeeId"), getRaisePercent() + "=>" + salary ); getViewRowImpl().setAttribute("Salary", salary); } public void setRaisePercent(double raisePercent) { this.raisePercent = raisePercent; } public double getRaisePercent() { return raisePercent; } }
In the Application Navigator, right click the RaiseAction.java
and from the list select Make.
You just created a new Java class. You import this class as a Java fact type in Rules Designer to use later when you create rules.
To create the Java fact type:
In Rules Designer, select the ManagerRules.rules
dictionary.
Click the Facts navigation tab and select the Java Facts tab.
Click Create....
In the Create Java Fact dialog, in the Classes area navigate in the tree and expand com
and example
to display the RaiseAction checkbox.
Select the RaiseAction checkbox as shown in Figure 10-18.
Figure 10-18 Create Java Fact from Raise Action Class
Click OK.
This adds the Raise Action fact type to the Java Facts table.
This rule shows how to use action types to update database entries.
To add 12 year raise rule:
In Rules Designer in the Raises Ruleset, click Create Rule.
Change the rule name by selecting Rule_1 and entering the value: Longer than 12 years
.
Click Show Advanced Settings. For more information, see Section 4.5.1, "How to Show and Hide Advanced Settings in a Rule or Decision Table".
Select Advanced Mode.
Enter the 12 year raise rules, as shown in Figure 10-19.
Figure 10-19 Adding the Longer Than 12 Years Rule to the Raises Ruleset
Now create the decision function for the employee raises and the retract all employees rulesets.
To add a decision function:
Click the Decision Functions navigation tab.
In the Decision Functions area, click Create.... This displays the Edit Decision Function dialog.
Update the decision function fields as shown in Figure 10-20.
Enter Name value EmployeeRaises
.
In the Inputs area, click the Add Input and edit the input information as follows:
Click the Fact Type field and select Employee from the list.
In this decision function you do not define any outputs, because you use the ActionType
API for taking action rather than producing output.
In the Rulesets & Decision Functions area, move the following items from the Available area to the Selected area, in the specified order.
DecisionPointDictionary.Preprocessing
Raises Ruleset
Retract Employees Ruleset
DecisionPointDictionary.Postprocessing
Figure 10-20 Adding the Employee Raises Decision Function
Ensure that the items in the Selected area are in the order shown in Figure 10-20.
If they are not, select an item and use the Move Up and Move Down buttons to correct the order.
Click OK.
Add the employee raises class. This executes the decision function.
To add the employee raises class:
Select the Chapter10 project.
Right-click and select New....
In the New Gallery, in the Categories area select General.
In the New Gallery, in the Items area, select Java Class.
Click OK.
In the Name field, enter EmployeeRaises
.
Click OK.
Replace the contents of this class with the code shown in Example 10-11.
Example 10-11 DeptManagerFinder Class
package com.example; import oracle.jbo.ApplicationModule; import oracle.jbo.ViewObject; import oracle.jbo.client.Configuration; import oracle.jbo.server.DBTransactionImpl2; import oracle.rules.rl.exceptions.RLException; import oracle.rules.sdk2.decisionpoint.DecisionPoint; import oracle.rules.sdk2.decisionpoint.DecisionPointBuilder; import oracle.rules.sdk2.decisionpoint.DecisionPointInstance; import oracle.rules.sdk2.exception.SDKException; import oracle.rules.sdk2.repository.DictionaryFQN; public class EmployeeRaises { private static final String AM_DEF = "com.example.AppModule"; private static final String CONFIG = "AppModuleLocal"; private static final String VO_NAME = "EmployeesView1"; private static final String DF_NAME = "EmployeeRaises"; private static final DictionaryFQN DICT_FQN = new DictionaryFQN("com.example", "Chapter10Rules"); private DecisionPoint dp = null; public EmployeeRaises() { try { dp = new DecisionPointBuilder() .with(DICT_FQN) .with(DF_NAME) .build(); } catch (SDKException e) { System.err.println(e); } } public void run() { final ApplicationModule am = Configuration.createRootApplicationModule(AM_DEF, CONFIG); final ViewObject vo = am.findViewObject(VO_NAME); final DecisionPointInstance point = dp.getInstance(); point.setTransaction((DBTransactionImpl2)am.getTransaction()); point.setAutoCommit(true); point.setViewObject(vo); try { point.invoke(); } catch (RLException e) { System.err.println(e); } catch (SDKException e) { System.err.println(e); } for (DecisionPoint.NamedValue result : point.getResults()){ System.out.println(result.getName() + " " + result.getValue()); } } public static void main(String[] args) { new EmployeeRaises().run(); } }
Copy the updated dictionary to the MDS accessible location.
Copy dictionary to MDS accessible location:
In a file system navigator, outside of Oracle JDeveloper, navigate to the Chapter10 folder and the Chapter10 project and copy the oracle directory that contains the dictionary.
In the application directory for Chapter10, above the Chapter10 project, navigate to the .adf
directory.
Copy the oracle folder to this directory.
You can build and test the project by running employee raises ruleset.
Build the project:
From the menu next to Run icon, select Manage Run Configurations....
In the Project Properties dialog, click New....
In the Create Run Configuration dialog, enter the name. For example, enter EmployeeRaises
.
In the Copy Settings From field, enter Default.
Click OK.
With EmployeeRaises selected, click Edit....
In the Default Run Target field, click Browse....
Select EmployeeRaises.java from the src\com\example
folder.
Click Open.
In the Edit Run Configuration dialog, click OK.
In the Project Properties dialog, click OK.
Run the project:
In the menu next to the Run project icon, select EmployeeRaises.
Oracle JDeveloper displays the output as shown in Example 10-12.
Example 10-12 Output from Raises Ruleset
raise for 100 0.03=>81.7 raise for 101 0.03=>1872.46 raise for 102 0.03=>60596.78 raise for 103 0.03=>31146.26 raise for 104 0.03=>20159.43 raise for 108 0.03=>35822.68 raise for 109 0.03=>26084.5 raise for 114 0.03=>27500.92 raise for 115 0.03=>7524.5 raise for 120 0.03=>16262.34 raise for 121 0.03=>16183.41 raise for 122 0.03=>15591.35 raise for 131 0.03=>3671.33 raise for 133 0.03=>4567.98 raise for 137 0.03=>4838.1 raise for 141 0.03=>4703.71 raise for 142 0.03=>4044.79 raise for 145 0.03=>17734.79 raise for 146 0.03=>17101.39 raise for 147 0.03=>15201.23 raise for 150 0.03=>12667.7 raise for 151 0.03=>12034.32 raise for 156 0.03=>13047.73 raise for 157 0.03=>12395.35 raise for 158 0.03=>11400.93 raise for 159 0.03=>10134.16 raise for 168 0.03=>14567.86 raise for 174 0.03=>13934.48 raise for 175 0.03=>11147.58 raise for 184 0.03=>5480.03 raise for 185 0.03=>5193.76 raise for 192 0.03=>5219.1 raise for 193 0.03=>4940.41 raise for 200 0.03=>5740.99 raise for 201 0.03=>16962.05 raise for 203 0.03=>8481.03 raise for 204 0.03=>13047.73 raise for 205 0.03=>15657.27 raise for 206 0.03=>10829.62