« November 2008 | Main | March 2009 »

December 2008 Archives

December 1, 2008

Multiple imports or includes in an XML Schema

A common way to modularize a large XML schema is to divide the schema into multiple documents and then "import" or "include" these documents into a primary schema document. For more information on these techniques, see this page.

However, sometimes users will encounter an error like the one below when trying to import it into a dictionary:

[ERROR] src-resolve: Cannot resolve the name 'ns0:Header' to a(n) 'type definition' component. line 13 of baz.xsd

This error indicates that the imported schema has multiple imports with the same namespace. The XML Schema specification says that it's at the discretion of the parser whether or not it wants to acknowledge all of them, and most don't. Xerces is the parser used in WebLogic, and does not. An import has the meaning of "components from namespace X might be found in schema Y," so the parser looks in one of them and then returns that the component cannot be found. The name which the error indicates is in one of the ignored schemas, so the name can't be found.

The most common way around this is to create a schema that includes all of the schemas you want to have in the same namespace, and then import that schema into your primary schema.

Example:
intermediate.xsd:


<schema targetNamespace="foobar" ...>
<include schemaLocation="foo.xsd"/>
<include schemaLocation="bar.xsd"/>
...
</schema>

<schema targetNamespace="baz" ...>
<import namespace="foobar" schemaLocation="intermediate.xsd"/>
...
</schema>

Also, it is common to use <import /> when the target schema has a targetNamespace, and use <include /> when the target schema does not have a targetNamespace.


December 3, 2008

Rules from BPEL: Decision Service Usage Patterns Explained (10.1.3)

Introduction

The integrated way to use Oracle Business Rules (OBR) from a BPEL process is via the Decision Service component through a Decide activity. Chapter 18 BPEL Process Integration with Business Rules of the Oracle BPEL Process Manager Developer's Guide explains the basic steps for doing this, but there's always more information than can go in the official documentation. This post explains in greater detail how to use the various decision service configurations.

Stateful vs. stateless

By default, the decision service is invoked as a stateful service. This allows the same decision service instance to be called more than once within the same BPEL process instance and maintain state between calls. For example, we may retrieve some data from a database, make a call to a stateful decision service, branch in our process based on the result, access the database again, and call the stateful decision service again with our additional data.

If you are only making one call to a decision service within a BPEL process using the "Assert facts, execute rule set, and retrieve results" operation type, consider changing the decision service to be stateless. This will improve performance because a stateful service invocation creates a new rule engine instance for each call, whereas a stateless service maintains a pool of services that can be reused. Thereby, the stateless service call has lower CPU overhead for creating the service instance and does not require additional memory because the rule engine instances already exist as part of the pool.

Ruleset invocation type

The Ruleset invocation type allows you to select from several Operation types, as described in section 18.4.3.1 "Mapping Input and Output Facts to BPEL Variables" of the BPEL Developer's Guide. The most common usage is the "Assert facts, execute rule set, and retrieve results" type as a stateless session. The other operation options are usually used for stateful sessions, whereby we want to maintain the state of the decision service between multiple calls, for example, if we wanted to use facts generated in the rules engine during one call as available to another call.

RulesetOptions.jpg

The primary advantage of using the Ruleset invocation type is it's simplicity, as the assert, execute, and retrieve operations are easily defined with in the Decide component. The primary disadvantage of using the Ruleset invocation type is that only rules from one ruleset will be evaluated. You cannot evaluate multiple rulesets against the same facts or use a pattern by which rules in one ruleset causes additional ruleset to be evaluated via the pushRuleset mechanism, because only the named ruleset is created in the rule engine instance.

Note that if you have multiple calls to the same decision service within a BPEL process, even these calls do not maintain state between them, it is preferred to use a stateful session. This way, if the rules are modified during the lifetime of the process, the process will still use the rules which existed when the process started. Otherwise, there is a possibility that different rules can be used for different invocations of the decision service. Multiple calls to a stateful decision service that do not (or should not) maintain state between them should be invoked with the operation "Assert facts, execute rule set, retrieve results, and reset the session", so any facts in the rule engine are removed between calls.

Function invocation type

The most useful invocation type in the decision service is to call a function defined in the rules dictionary. This allows the user greatest flexibility in how the rules are used. However, this pattern also requires the user to perform some actions which can be automatically performed with the Ruleset invocation type.

FunctionOptions.jpg

There are two operation types for the Function invocation type, "Execute function" and "Execute function and reset the session". These have equivalent functionality when called as part of a stateless decision service. When called from a stateful decision service, resetting the session will cause all facts to be retracted, as with the similar Ruleset operation type.

A function called from the decision service by this invocation type must meet the following requirements:


  1. return a XML Schema element type
  2. accept one or more XML Schema element types as parameters.

It is necessary that the return and parameter types be XML Schema element types rather than XML Schema complex types. If complex types are used, the functions will not appear in the dictionary browser and therefore cannot be selected.

The body of this function must do three things:

  1. assert the input parameters as facts
  2. push one or more rulesets onto the ruleset stack
  3. call the "run" method

An example of a function which can be called from the decision service is shown below:

DecisionServiceFunctionExample.jpg

Function body:

assertXPath("com.oracle.fmw.obr.test1", email, "//*");
pushRuleset("RULESET_1");
run();
return email;

This is a very simple function body. The function body can assert any number of parameters and push any number of rulesets onto the stack.


December 9, 2008

Making rules repository access faster (10.1.3)

This post describes a performance enhancement available in the 10.1.3.3 and 10.1.3.4 releases which can significantly speed up the repository access, particularly in dictionaries with large numbers of rulesets.

By default in 10.1.3, the rules repository stores each ruleset in a separate XML document. In a file-based repository, these documents are stored within a zip file. In a WebDAV repository, these documents are stored in a WebDAV-visible directory. This default mode for storing the rulesets is known as "multiple document format". This format was first used in the 10.1.3.1 release, and continued through to the 10.1.3.3 and 10.1.3.4 releases for backwards compatibility. However, multiple document format has negative performance ramifications, particularly with large numbers of rulesets in a WebDAV repository. The 10.1.3.3 and 10.1.3.4 releases also have the option of storing all rulesets in a single document to provide better performance. Multiple document format repositories must be manually converted to single document format to take advantage of these performance benefits.

The following utility will convert a rule repository to single document format. All dictionaries that are not in single document format are converted. Once the repository is converted, all new dictionaries that are created will be in single document format. This utility is contained in the rulesdk.jar file.

These classes are required on the classpath when running these commands: xmlparserv2.jar, xmlmesg.jar, xml.jar, orai18n.jar, oraclepki.jar, ojpse.jar, http_client.jar, rl.jar, rulesdk.jar, jr_dav.jar, webdavrc.jar.

java oracle.rules.sdk.repository.SingleDocumentFormat
-type repository_type
-path file_path | -url webdav_url [-wallet wallet_path]
where
repository_type is either file or webdav
file_path is the path to a file repository
webdav_url is the URL for a WebDAV repository
wallet_path is the path to an Oracle wallet containing WebDAV credentials
A file_path or a webdav_url must be provided.

Additionally, there is a similar utility that converts a rule repository from single document format to the multiple document format. All dictionaries that are not in multiple document format are converted. Once the repository is converted, all new dictionaries that are created will be in multiple document format.

java oracle.rules.sdk.repository.MultipleDocumentFormat
-type repository_type
-path file_path | -url webdav_url [-wallet wallet_path]
where
repository_type is either file or webdav
file_path is the path to a file repository
webdav_url is the URL for a WebDAV repository
wallet_path is the path to an Oracle wallet containing WebDAV credentials

A file_path or a webdav_url must be provided.

December 15, 2008

File-based rules repository in a BPEL Decision Service (10.1.3)

In 10.1.3, the two types of rule repositories are file-based and WebDAV. WebDAV is recommended for production deployment, but some people may still want to use a file-based repository. Support for product lifecycle is not as strong when using a file-based repository, so this post describes the manual steps that must be performed.

When you deploy the BPEL process with a decision service that uses file repository, a copy of repository is packaged with the decision service. The decision service refers to this copy when executing. To modify the rules without redeploying the BPEL process, you must modify this copy on the server. To do this, go to the BPEL Console, click on your BPEL process, and go to the descriptor tab. This page contains a link to open the deployed rule repository using Rule Author.

Changes to the deployed dictionary will be reflected in decision service instances created after the dictionary is saved. A stateless decision service keeps a pool of rule engine instances which it re-uses, and will refresh these instances with new ones when it detects the dictionary has changed. A stateful decision service creates a new rule engine instance every time it is invoked and will always be created with the latest version of the dictionary.

If you make changes to the deployed file-based dictionary, you must manually copy this file back into your JDeveloper project if you wish to have the changes persist in the next deployment of the decision service.


December 16, 2008

Enabling debug output in a BPEL Decision Service (10.1.3)

Section 18.7.2 of the Oracle BPEL Process Manager Developer's Guide 10g (10.1.3.1.0) contains instructions for enabling debug logging for a decision service. However, unless you are familiar with BPEL debugging already, there is one step missing. The logging is at the "debug" level, but the BPEL server sets the logging level to "info" by default.

To change the logging level to "debug" so you can see the logging information from your rules:


  • From the BPEL Control panel, click on the "Configuration" tab.
  • From that tab, click on the "Logging" sub-tab.
  • For the "Logger Name" "default.collaxa.cube.engine.bpel", select "Debug" for the "Logging Level.
  • Click the Apply button at the bottom of the page.

Debugging output is now enabled and will be available in the OPMN log for the domain in which the process is deployed.

December 17, 2008

File-based vs. WebDAV Rule Repositories (10.1.3)

In production, it is recommended to use the WebDAV repository option. However, during development, this can be laborious, since the WebDAV repository is slower than the file-based repository, as it usually on a remote machine. Additionally, if the WebDAV repository connection is over a slow link, the UI can pause for several seconds at a time while the repository is accessed. The latency usually isn't an issue at runtime because the repository is accessed infrequently by the running decision service. However, during design-time, it can be advantageous to use a file-based repository for development and then change the decision service configuration to use WebDAV when the application is ready for production deployment.

There are two primary things that need to be done: (1) moving the dictionary or dictionaries from the file-based repository to the WebDAV repository, and (2) changing the decision service to use the WebDAV connection.

I've seen people try to just copy their file-based repository to their WebDAV repository, but this will not work. The repository itself is nothing more than a collection of appropriately named XML files representing the rules. A file-based repository is a zip file of these files, and a WebDAV repository is a directory of these files. So, copying the file-based repository into the WebDAV directory is putting a repository inside another repository!

To move a dictionary between a file and WebDAV repository or vice-versa:
1) In Rule Author, connect to the source repository.
2) Choose the "export" tab.
3) Export the dictionary and download the resulting export file.
4) Disconnect from the source repository.
5) Connect to the destination repository.
6) Choose the "import" tab.
7) Select the previously exported file and import that file.
8) Save the dictionary.
9) Done!

The next step is to modify the decision service to use the WebDAV repository. To do this, open the file:

JDev_Oracle_Home\jdev\mywork\application_name\
process_name\decisionservices\DecisionService\war\WEB-INF\
classes\decisionservices.xml

In the ruleEngineProvider element, "repository" element must be changed from something like:

<repository type="File">
<file>repositoryresource:CreditRatingRepository</file>
</repository>

to something like:

<repository type="WebDAV">
<webdav>
<url>http://myhost.mydomain.com:8080/rules/repository/</url>
<username>bob</username>
<password encrypted="true">r9CqG45+Cg=</password>
</webdav>
</repository>

Instead of manually creating the "webdav" element in decisionservices.xml, I usually create a new decision servce which uses the WebDAV repository and then copy the "repository" element created for that decision service into the one I want to change. This way, there's much less chance of a typo and I don't have to manually encrypt the password.

Three quick decision service tips (10.1.3)

Assert Fact and Watch Fact
If the same fact type instance is used for input and output to the decision service, both Assert Fact and Watch Fact must be checked for that fact type in the decision service wizard.

Editing a decision service
The only way to edit a decision service is to begin to create a new Decide activity. Click on the edit "pencil" icon. However, the only thing you can only change the function or ruleset which is called. Also note that when you edit the decision service, the Decision Service drop down menu is reset, to the decision service you selected to edit is no longer selected and must be reselected. If you need to change anything other than the function or ruleset called, you must create a new decision service.

Creating a Decision Service which uses a WebDAV repository
You cannot access the WebDAV connection wizard after starting the decision service wizard, so you must create the WebDAV connection from the Connections tab before starting the decision service wizard.


Asserting an entire XML document (10.1.3)

When one calls the normal "assert" function on an object, only that fact is asserted. OBR also allows you to assert an object graph consisting of JAXB objects representing an XML document with the "assertXPath" function. This will assert the tree of objects starting with object passed to the function. The most common path to assert is "//*", meaning the entire subtree, but any arbitrary XPath can be used. assertXPath will assert only objects for which there is a 1-to-many relationship with the parent object. In the JAXB generated code, by default this is represented by a property of List type.

Objects in the hierarchy with a 1-to-1 relationship with their parent can be accessed directly via their parent's property, so it is not necessary to assert them in most cases. This also means that when a schema definition has an object hierarchy with a 1-to-1-to-many relationship, the child and grandchild objects will not be asserted. Some schemas define this type of relationship explicitly, but it can also occur in some situations when anonymous complex types are used.

If the user wishes to have the entire tree below the 1-to-1 relationship asserted, then this tree must be explicitly asserted. One way to do this is to write a rule that will match the parent fact type and call assertXPath with the the child fact type instance as an argument. This rule can then be made to run before all other rules. In the case of invoking a single ruleset from a decision service, this rule should be in the invoked ruleset with a priority higher than all other rules in the ruleset. In the case of invoking a function, the rule should be in a ruleset which is pushed onto the ruleset stack last, so it will be executed first. Because the rule will only match on the fact type, and not any of the properties of the fact type instance, the rule must be written like:

if (fact Parent p && not exists (fact Child c && p.child != c) )

Meaning, the parent exists but the child does not. If only the parent fact is matched, then the rule will re-fire anytime the parent fact is changed, reasserting the child and re-firing any rules which depend on the child. In Rule Author, "not exists" is implemented using the "there is no case where" form of a pattern.

When creating a decision service which invokes a single ruelset, there is a checkbox labeled "Check here to assert all decendants from the top level element". This will cause the decision service to use assertXPath with the path as "//*" instead of the default of only asserting the root object. If you wish to assert something other than "//*" in the decision service, the decisionservice.xml file can be edited to replace "//*" with the desired XPath expression.

December 18, 2008

Rules Resources

This post gathers together some of the resources for learning how to do rules programming, and specifically how to use Oracle Business Rules.


Currently, all publicly available documentation from Oracle is for the 10.1.3 version of OBR:

For questions or issues with OBR, the
SOA Suite category on the Oracle Forums is the the best place to go.

Unfortunately, there aren't many books on rules programming out there. Here are a few of the relevant ones:

  • Jess in Action by Ernest Friedman-Hill - while the Lisp-style syntax may be daunting to many OO programmers, there's a lot of good information on how rules engines work in practice and on how to write rules.
  • Smart (Enough) Systems by James Taylor and Neil Raden - this book mostly focuses on the business case for improved decision support, but has an excellent chapter on the current state of business rules engines (BRE) and business rules management systems (BRMS).
  • Expert Systems: Principles and Programming by Giarratano and Riley - a thorough and deeply technical description of rules principles.
  • Introduction to Expert Systems by Peter Jackson - another very technical book

Plenty to get you started in the wonderful world of rules!

Smart Business Processes with Oracle Business Rules

We've just put a new whitepaper on Smart Business Processes with Oracle Business Rules on our official site.

About December 2008

This page contains all entries posted to Oracle Business Rules in December 2008. They are listed from oldest to newest.

November 2008 is the previous archive.

March 2009 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle