Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Oracle SOA Suite 11g R1 Developer's Guide

You're reading from   Oracle SOA Suite 11g R1 Developer's Guide Service-Oriented Architecture (SOA) is made easily accessible thanks to this comprehensive guide. With a logically structured approach, it gives you the expertise to start using the Oracle SOA suite in real-world applications.

Arrow left icon
Product type Paperback
Published in Jul 2010
Publisher Packt
ISBN-13 9781849680189
Length 720 pages
Edition 1st Edition
Arrow right icon
Toc

Chapter 7. Using Business Rules to Define Decision Points

At runtime, there may be many potential paths through a BPEL process, controlled by conditional statements such as switch or while activities. Typically, the business rules that govern which path to take at any given point are written as XPath expressions embedded within the appropriate activity.

Although this is an acceptable approach, we often find that while the process itself may be relatively static, the business rules embedded within the activities may change on a more frequent basis. This will require us to update the BPEL process and redeploy it, even though the process flow itself hasn't changed.

In addition, by embedding the rule directly within the decision point, we often end up having to reimplement the same rule every time it is used, either within the same process or across multiple processes. Apart from being inefficient, this can lead to inconsistent implementations of the rules, as well as requiring us to update the rules in multiple places every time it changes.

The Oracle Business Rules engine that comes as part of the SOA Suite provides a declarative mechanism for defining business rules externally to our application. This not only ensures that each rule is used in a consistent fashion, but in addition, it makes it simpler and quicker to modify. We only have to modify a rule once and can do this with almost immediate effect, thus increasing the agility of our solution.

For those of you familiar with 10gR3, you will notice that JDeveloper comes with a new rules editor which is a lot more intuitive and simpler to use than the old browser-based editor. In addition, 11gR1 introduces decision tables , which provide a spreadsheet-like format for defining rules. While still very much a developer-oriented tool, these improvements make the tool a lot friendlier for business analysts, allowing them to better understand the rules that have been written as well as make simple changes.

In this chapter, we will introduce the new rules editor and look at how we can use it to define a decisions service to automate the approval of leave requests. Then, once we've done this, we'll see how to invoke the rule from the leave approval BPEL process. We will first implement these as a standard set of rules and then examine how we can simplify these rules by using a decision table.

Business rule concepts

Before we implement our first rule, let's briefly introduce the key components which make up a business rule. These are:

  • Facts: Represent the data or business objects that rules are applied to.
  • Rules: A rule consists of two parts, namely, an IF part that consists of one or more tests to be applied to a fact(s), and a THEN part that lists the actions to be carried out, should the test evaluate to true.
  • Rule Set: As the name implies, it is just a set of one or more related rules that are designed to work together.
  • Dictionary: A dictionary is the container of all components that make up a business rule. It holds all the Facts, Rule Sets, and Rules for a business rule.

In addition, a dictionary may also contain decision tables, functions, variables, and constraints. We will introduce these in more detail later in this chapter.

To execute a business rule, you assert (submit) one or more facts to the rules engine. It will apply the rules to the facts, that is, each fact will be tested against the IF part of the rule, and if it evaluates to true, then it will perform the specified actions for that fact. This may result in the creation of new facts or the modification of existing facts (which may result in further rule evaluation).

XML facts

The rule engine supports four types of facts: Java Facts , XML Facts, RL Facts, and ADF Facts . The type of fact that you want to use typically depends on the context in which you will be using the rules engine.

For example, if you are calling the rule engine from Java, then you would work with Java Facts as this provides a more integrated way of combining the two components. As we are using the rule engine within a composite, it makes sense to use XML facts.

The rule editor uses XML schemas to generate JAXB 2.0 classes, which are then imported to implement the corresponding XML facts. Using JAXB, particularly when used in conjunction with BPEL, places a number of constraints on how we define our XML schemas, including:

  • Within BPEL, you can only define variables based on globally defined elements. Thus all input and output facts passed to the decision service must be defined as global elements within our XML schemas.
  • When defining the input and output facts for any complexType (for example, tLeaveRequest), there can only be one global element of that type (for example, leaveRequest).
  • The element naming convention for JAXB means that elements or types with underscores in their names can cause compilation errors.

Decision services

To invoke a business rule within a composite, we need to go through a number of steps. First, we must create a session with the rules engine, then we can assert one or more facts, before executing the ruleset and finally we can retrieve the results.

We do this via a decision service (or function). This is essentially a web-service wrapper around a rules dictionary, which takes care of managing the session with the rules engine as well as governing which ruleset we wish to apply.

The wrapper allows a composite to assert one or more facts, execute a ruleset(s) against the asserted facts, retrieve the results, and then reset the session. This can be done within a single invocation of an operation or over multiple operations.

Leave approval business rule

For our first rule, we are going to build on our leave request example from the previous chapter, Adding in Human Workflow. If you remember, we implemented a simple process requiring every leave request to go to an individual's manager for approval. However, what we would like is a rule that automatically approves a request as long as it meets certain company guidelines.

To begin with, we will write a simple rule to automatically approve a leave request that is of the type Vacation and only for one day's duration. This is a pretty trivial example, but once we've done this, we will look at how to extend this rule to handle more complex examples.

Creating a decision service

Within JDeveloper, open up your LeaveApproval application from the previous chapter (or alternately open the sample provided with the book). Open up the composite.xml file for the application and then from the Component Palette, drag-and-drop a Business Rule onto the composite, as shown in the following screenshot:

Creating a decision service

This will launch the Create Business Rules dialog, as shown in the following screenshot:

Creating a decision service

The first step is to give our dictionary a name, such as LeaveApprovalRules, and a corresponding Package name.

In addition, we need to specify the Input and Output facts that we will pass to our decision service. For our purpose, we will pass in a single leave request. The rule engine will then apply the rules that we define and update the status of the leave request to either Approved or Manual (to indicate the request needs to be manually approved).

So we need to define a single input fact and output fact, both of type leaveRequest. To do this, click on the plus symbol (marked in the preceding screenshot), and select Input.

This will bring up the standard Type Chooser window; browse the LeaveRequest.xsd and select leaveRequest. Do the same again to specify an Output fact.

Note

When creating facts based on an XML schema, the rules editor will generate corresponding JAXB Java classes and place them in the specified Package. It is a good practice to specify a different package name for every XML schema to prevent conflicting class definitions.

Next, click the Advanced tab. Here we can see that JDeveloper has given the default name LeaveApprovalRules_DecisionService_1 to our decision service. Give it a more meaningful name such as LeaveApprovalDecisonService.

Creating a decision service

Now click OK. JDeveloper will inform you that it is creating the business rule dictionary for LeaveApprovalRules. Once completed, your composite should now look as shown in the following screenshot:

Creating a decision service

We are now ready to implement our business rules. Double-click on the LeaveApprovalRules component, and this will launch the rules editor, which is shown in the next screenshot.

Implementing our business rules

The rules editor allows you to view/edit the various components which make up your business rules. To select a particular component, such as Facts, Functions, Globals, and so on, just click on the corresponding tab down the left-hand side.

Implementing our business rules

You will see that, by default, JDeveloper has created a skeleton rules dictionary-based on the inputs we just specified.

Select the Facts tab (as shown in the preceding screenshot). You will see that it contains two XML facts (TLeaveRequest and com.packtpub.schemas.leaverequest.ObjectFactory), which are based on the inputs/outputs we defined earlier as well as a set of standard Java facts, which are automatically included within a rules dictionary.

Next, select the Decision Functions tab. You will see that it contains a single decision function LeaveApprovalDecisonService (that is, the name we specified on the Advanced tab when creating our business rule).

We will introduce some of the other tabs later in this chapter, but for the time being, we will start by defining our first rule. By default, the rules editor will have created a single ruleset with the name Ruleset_1. Click on the Ruleset_1 tab to open up the ruleset within the editor.

Expand the ruleset to show its details by clicking on the plus symbol (circled in the following screenshot). We can see that the ruleset has three properties: Name, Description, and Effective Date.

The Effective Date enables us to specify a period in time for which the ruleset will be applied, allowing you to define multiple versions of the same ruleset. For example, a current ruleset and a future version that we wish to come into effect at a defined time in the future.

Rename the ruleset to something more meaningful, for example, Employee Leave Approval Policy; add a description if you want and ensure that Effective Date is set to Always Valid.

Adding a rule to our ruleset

To add a rule, click the green plus symbol on the top-right-hand corner, and select Create Rule, as shown in the following screenshot (alternatively click on the Create Rule button, circled in the following screenshot).

Adding a rule to our ruleset

This will add a rule to our ruleset with the default name Rule_1, as shown in the following screenshot. Here, we can see that a rule consists of two parts, an IF part, which consists of one or more tests to be applied to a fact or facts, and a THEN part, which specifies the actions to be carried out, should the test evaluate to true.

To give the rule a more meaningful name, simply click on the name and enter a new name (for example, One Day Vacation). By clicking on the <enter description> element, you can also add a description for the rule.

Adding a rule to our ruleset

Creating the IF clause

For our leave approval rule, we need to define two tests, one to check that the request is only for a day in duration, which we can do by checking that the start date equals the end date, and the second to check that the request is of type Vacation.

To define the first test, click on <insert test>. This will add the line <operand> = = <operand> under the IF statement where we can define the test condition.

Creating the IF clause

Click on the first <operand>. This will display a drop-down list listing the valid facts and their attributes that we can test. From here, we can select the value to be tested, for example, TLeaveRequest.startDate in our case.

Creating the IF clause

Next from the operator drop-down list, select the test to be applied to the first operand (== in our case). We can either choose to compare it to a specified value or a second Operand. For our purpose, we want to check that the request.startDate equals the request.endDate, so click on the operand and select this from the drop-down list.

To create our second test, we follow pretty much the same process. This time we want to test that the operand leaveRequest.leaveType is equal to the value Vacation, so select the right-hand operator and type this in directly:

Creating the IF clause

Note, the rule editor has automatically inserted an and clause between our two tests. If you click on this, you have the option of changing this to an or clause.

Creating the Then clause

Now that we have defined our test, we need to define the action to take if the test evaluates to true. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out.

Creating the Then clause

The rule editor allows us to choose from the following action types:

  • assert new: We use this to create and assert a new fact, for example, a new LeaveRequest. Once asserted, the new fact will be evaluated by the rules engine against the ruleset.
  • modify: We can use this to either assign a value to a variable or a fact attribute; in our case we want to assign a status of Approved to the requestStatus property.
  • retract: This enables you to retract any of the facts matched in the pattern (for example, TLeaveRequest) so that it will no longer be evaluated as part of the ruleset.
  • call: This allows you to call a function to perform one or more actions.

The actions assert new and retract are important when we are dealing with rulesets that deal with multiple interdependent facts, as this allows us to control which facts are being evaluated by the rule engine at any particular time. Here, we are only dealing with a single fact, so we don't examine these constructs in this chapter, leaving them to Chapter 18, Using Business Rules to Implement Services.

For our purposes, we want to update the status of our leave, so select modify. Our rule should now look as shown in the following screenshot:

Creating the Then clause

The next step is to specify the fact to be modified. Click on the <target> element and you will be presented with a list of facts that are within scope. In our case, this will only be the TLeaveRequest that has just been matched by the IF clause, so select this. Our rule will now appear, as shown in the following screenshot:

Creating the Then clause

We now need to specify the properties we wish to modify, click on <add property> to open the Properties dialog. This will display a list of all the facts properties, allowing us to modify them as appropriate.

Select the Value cell for requestStatus. From here, you can directly enter a value, select a value from the drop-down list, or launch the expression builder. For our purposes, just enter the string Approved, as shown in the following screenshot, and then click Close.

Creating the Then clause

We don't need to specify values for any of the other properties, as the rules engine will only update those properties where a new value has been specified.

This completes the definition of our first rule. The next step is to wire it into our BPEL process.

Creating the Then clause

Creating a decision service

Within JDeveloper, open up your LeaveApproval application from the previous chapter (or alternately open the sample provided with the book). Open up the composite.xml file for the application and then from the Component Palette, drag-and-drop a Business Rule onto the composite, as shown in the following screenshot:

Creating a decision service

This will launch the Create Business Rules dialog, as shown in the following screenshot:

Creating a decision service

The first step is to give our dictionary a name, such as LeaveApprovalRules, and a corresponding Package name.

In addition, we need to specify the Input and Output facts that we will pass to our decision service. For our purpose, we will pass in a single leave request. The rule engine will then apply the rules that we define and update the status of the leave request to either Approved or Manual (to indicate the request needs to be manually approved).

So we need to define a single input fact and output fact, both of type leaveRequest. To do this, click on the plus symbol (marked in the preceding screenshot), and select Input.

This will bring up the standard Type Chooser window; browse the LeaveRequest.xsd and select leaveRequest. Do the same again to specify an Output fact.

Note

When creating facts based on an XML schema, the rules editor will generate corresponding JAXB Java classes and place them in the specified Package. It is a good practice to specify a different package name for every XML schema to prevent conflicting class definitions.

Next, click the Advanced tab. Here we can see that JDeveloper has given the default name LeaveApprovalRules_DecisionService_1 to our decision service. Give it a more meaningful name such as LeaveApprovalDecisonService.

Creating a decision service

Now click OK. JDeveloper will inform you that it is creating the business rule dictionary for LeaveApprovalRules. Once completed, your composite should now look as shown in the following screenshot:

Creating a decision service

We are now ready to implement our business rules. Double-click on the LeaveApprovalRules component, and this will launch the rules editor, which is shown in the next screenshot.

Implementing our business rules

The rules editor allows you to view/edit the various components which make up your business rules. To select a particular component, such as Facts, Functions, Globals, and so on, just click on the corresponding tab down the left-hand side.

Implementing our business rules

You will see that, by default, JDeveloper has created a skeleton rules dictionary-based on the inputs we just specified.

Select the Facts tab (as shown in the preceding screenshot). You will see that it contains two XML facts (TLeaveRequest and com.packtpub.schemas.leaverequest.ObjectFactory), which are based on the inputs/outputs we defined earlier as well as a set of standard Java facts, which are automatically included within a rules dictionary.

Next, select the Decision Functions tab. You will see that it contains a single decision function LeaveApprovalDecisonService (that is, the name we specified on the Advanced tab when creating our business rule).

We will introduce some of the other tabs later in this chapter, but for the time being, we will start by defining our first rule. By default, the rules editor will have created a single ruleset with the name Ruleset_1. Click on the Ruleset_1 tab to open up the ruleset within the editor.

Expand the ruleset to show its details by clicking on the plus symbol (circled in the following screenshot). We can see that the ruleset has three properties: Name, Description, and Effective Date.

The Effective Date enables us to specify a period in time for which the ruleset will be applied, allowing you to define multiple versions of the same ruleset. For example, a current ruleset and a future version that we wish to come into effect at a defined time in the future.

Rename the ruleset to something more meaningful, for example, Employee Leave Approval Policy; add a description if you want and ensure that Effective Date is set to Always Valid.

Adding a rule to our ruleset

To add a rule, click the green plus symbol on the top-right-hand corner, and select Create Rule, as shown in the following screenshot (alternatively click on the Create Rule button, circled in the following screenshot).

Adding a rule to our ruleset

This will add a rule to our ruleset with the default name Rule_1, as shown in the following screenshot. Here, we can see that a rule consists of two parts, an IF part, which consists of one or more tests to be applied to a fact or facts, and a THEN part, which specifies the actions to be carried out, should the test evaluate to true.

To give the rule a more meaningful name, simply click on the name and enter a new name (for example, One Day Vacation). By clicking on the <enter description> element, you can also add a description for the rule.

Adding a rule to our ruleset

Creating the IF clause

For our leave approval rule, we need to define two tests, one to check that the request is only for a day in duration, which we can do by checking that the start date equals the end date, and the second to check that the request is of type Vacation.

To define the first test, click on <insert test>. This will add the line <operand> = = <operand> under the IF statement where we can define the test condition.

Creating the IF clause

Click on the first <operand>. This will display a drop-down list listing the valid facts and their attributes that we can test. From here, we can select the value to be tested, for example, TLeaveRequest.startDate in our case.

Creating the IF clause

Next from the operator drop-down list, select the test to be applied to the first operand (== in our case). We can either choose to compare it to a specified value or a second Operand. For our purpose, we want to check that the request.startDate equals the request.endDate, so click on the operand and select this from the drop-down list.

To create our second test, we follow pretty much the same process. This time we want to test that the operand leaveRequest.leaveType is equal to the value Vacation, so select the right-hand operator and type this in directly:

Creating the IF clause

Note, the rule editor has automatically inserted an and clause between our two tests. If you click on this, you have the option of changing this to an or clause.

Creating the Then clause

Now that we have defined our test, we need to define the action to take if the test evaluates to true. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out.

Creating the Then clause

The rule editor allows us to choose from the following action types:

  • assert new: We use this to create and assert a new fact, for example, a new LeaveRequest. Once asserted, the new fact will be evaluated by the rules engine against the ruleset.
  • modify: We can use this to either assign a value to a variable or a fact attribute; in our case we want to assign a status of Approved to the requestStatus property.
  • retract: This enables you to retract any of the facts matched in the pattern (for example, TLeaveRequest) so that it will no longer be evaluated as part of the ruleset.
  • call: This allows you to call a function to perform one or more actions.

The actions assert new and retract are important when we are dealing with rulesets that deal with multiple interdependent facts, as this allows us to control which facts are being evaluated by the rule engine at any particular time. Here, we are only dealing with a single fact, so we don't examine these constructs in this chapter, leaving them to Chapter 18, Using Business Rules to Implement Services.

For our purposes, we want to update the status of our leave, so select modify. Our rule should now look as shown in the following screenshot:

Creating the Then clause

The next step is to specify the fact to be modified. Click on the <target> element and you will be presented with a list of facts that are within scope. In our case, this will only be the TLeaveRequest that has just been matched by the IF clause, so select this. Our rule will now appear, as shown in the following screenshot:

Creating the Then clause

We now need to specify the properties we wish to modify, click on <add property> to open the Properties dialog. This will display a list of all the facts properties, allowing us to modify them as appropriate.

Select the Value cell for requestStatus. From here, you can directly enter a value, select a value from the drop-down list, or launch the expression builder. For our purposes, just enter the string Approved, as shown in the following screenshot, and then click Close.

Creating the Then clause

We don't need to specify values for any of the other properties, as the rules engine will only update those properties where a new value has been specified.

This completes the definition of our first rule. The next step is to wire it into our BPEL process.

Creating the Then clause

Implementing our business rules

The rules editor allows you to view/edit the various components which make up your business rules. To select a particular component, such as Facts, Functions, Globals, and so on, just click on the corresponding tab down the left-hand side.

Implementing our business rules

You will see that, by default, JDeveloper has created a skeleton rules dictionary-based on the inputs we just specified.

Select the Facts tab (as shown in the preceding screenshot). You will see that it contains two XML facts (TLeaveRequest and com.packtpub.schemas.leaverequest.ObjectFactory), which are based on the inputs/outputs we defined earlier as well as a set of standard Java facts, which are automatically included within a rules dictionary.

Next, select the Decision Functions tab. You will see that it contains a single decision function LeaveApprovalDecisonService (that is, the name we specified on the Advanced tab when creating our business rule).

We will introduce some of the other tabs later in this chapter, but for the time being, we will start by defining our first rule. By default, the rules editor will have created a single ruleset with the name Ruleset_1. Click on the Ruleset_1 tab to open up the ruleset within the editor.

Expand the ruleset to show its details by clicking on the plus symbol (circled in the following screenshot). We can see that the ruleset has three properties: Name, Description, and Effective Date.

The Effective Date enables us to specify a period in time for which the ruleset will be applied, allowing you to define multiple versions of the same ruleset. For example, a current ruleset and a future version that we wish to come into effect at a defined time in the future.

Rename the ruleset to something more meaningful, for example, Employee Leave Approval Policy; add a description if you want and ensure that Effective Date is set to Always Valid.

Adding a rule to our ruleset

To add a rule, click the green plus symbol on the top-right-hand corner, and select Create Rule, as shown in the following screenshot (alternatively click on the Create Rule button, circled in the following screenshot).

Adding a rule to our ruleset

This will add a rule to our ruleset with the default name Rule_1, as shown in the following screenshot. Here, we can see that a rule consists of two parts, an IF part, which consists of one or more tests to be applied to a fact or facts, and a THEN part, which specifies the actions to be carried out, should the test evaluate to true.

To give the rule a more meaningful name, simply click on the name and enter a new name (for example, One Day Vacation). By clicking on the <enter description> element, you can also add a description for the rule.

Adding a rule to our ruleset

Creating the IF clause

For our leave approval rule, we need to define two tests, one to check that the request is only for a day in duration, which we can do by checking that the start date equals the end date, and the second to check that the request is of type Vacation.

To define the first test, click on <insert test>. This will add the line <operand> = = <operand> under the IF statement where we can define the test condition.

Creating the IF clause

Click on the first <operand>. This will display a drop-down list listing the valid facts and their attributes that we can test. From here, we can select the value to be tested, for example, TLeaveRequest.startDate in our case.

Creating the IF clause

Next from the operator drop-down list, select the test to be applied to the first operand (== in our case). We can either choose to compare it to a specified value or a second Operand. For our purpose, we want to check that the request.startDate equals the request.endDate, so click on the operand and select this from the drop-down list.

To create our second test, we follow pretty much the same process. This time we want to test that the operand leaveRequest.leaveType is equal to the value Vacation, so select the right-hand operator and type this in directly:

Creating the IF clause

Note, the rule editor has automatically inserted an and clause between our two tests. If you click on this, you have the option of changing this to an or clause.

Creating the Then clause

Now that we have defined our test, we need to define the action to take if the test evaluates to true. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out.

Creating the Then clause

The rule editor allows us to choose from the following action types:

  • assert new: We use this to create and assert a new fact, for example, a new LeaveRequest. Once asserted, the new fact will be evaluated by the rules engine against the ruleset.
  • modify: We can use this to either assign a value to a variable or a fact attribute; in our case we want to assign a status of Approved to the requestStatus property.
  • retract: This enables you to retract any of the facts matched in the pattern (for example, TLeaveRequest) so that it will no longer be evaluated as part of the ruleset.
  • call: This allows you to call a function to perform one or more actions.

The actions assert new and retract are important when we are dealing with rulesets that deal with multiple interdependent facts, as this allows us to control which facts are being evaluated by the rule engine at any particular time. Here, we are only dealing with a single fact, so we don't examine these constructs in this chapter, leaving them to Chapter 18, Using Business Rules to Implement Services.

For our purposes, we want to update the status of our leave, so select modify. Our rule should now look as shown in the following screenshot:

Creating the Then clause

The next step is to specify the fact to be modified. Click on the <target> element and you will be presented with a list of facts that are within scope. In our case, this will only be the TLeaveRequest that has just been matched by the IF clause, so select this. Our rule will now appear, as shown in the following screenshot:

Creating the Then clause

We now need to specify the properties we wish to modify, click on <add property> to open the Properties dialog. This will display a list of all the facts properties, allowing us to modify them as appropriate.

Select the Value cell for requestStatus. From here, you can directly enter a value, select a value from the drop-down list, or launch the expression builder. For our purposes, just enter the string Approved, as shown in the following screenshot, and then click Close.

Creating the Then clause

We don't need to specify values for any of the other properties, as the rules engine will only update those properties where a new value has been specified.

This completes the definition of our first rule. The next step is to wire it into our BPEL process.

Creating the Then clause

Adding a rule to our ruleset

To add a rule, click the green plus symbol on the top-right-hand corner, and select Create Rule, as shown in the following screenshot (alternatively click on the Create Rule button, circled in the following screenshot).

Adding a rule to our ruleset

This will add a rule to our ruleset with the default name Rule_1, as shown in the following screenshot. Here, we can see that a rule consists of two parts, an IF part, which consists of one or more tests to be applied to a fact or facts, and a THEN part, which specifies the actions to be carried out, should the test evaluate to true.

To give the rule a more meaningful name, simply click on the name and enter a new name (for example, One Day Vacation). By clicking on the <enter description> element, you can also add a description for the rule.

Adding a rule to our ruleset

Creating the IF clause

For our leave approval rule, we need to define two tests, one to check that the request is only for a day in duration, which we can do by checking that the start date equals the end date, and the second to check that the request is of type Vacation.

To define the first test, click on <insert test>. This will add the line <operand> = = <operand> under the IF statement where we can define the test condition.

Creating the IF clause

Click on the first <operand>. This will display a drop-down list listing the valid facts and their attributes that we can test. From here, we can select the value to be tested, for example, TLeaveRequest.startDate in our case.

Creating the IF clause

Next from the operator drop-down list, select the test to be applied to the first operand (== in our case). We can either choose to compare it to a specified value or a second Operand. For our purpose, we want to check that the request.startDate equals the request.endDate, so click on the operand and select this from the drop-down list.

To create our second test, we follow pretty much the same process. This time we want to test that the operand leaveRequest.leaveType is equal to the value Vacation, so select the right-hand operator and type this in directly:

Creating the IF clause

Note, the rule editor has automatically inserted an and clause between our two tests. If you click on this, you have the option of changing this to an or clause.

Creating the Then clause

Now that we have defined our test, we need to define the action to take if the test evaluates to true. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out.

Creating the Then clause

The rule editor allows us to choose from the following action types:

  • assert new: We use this to create and assert a new fact, for example, a new LeaveRequest. Once asserted, the new fact will be evaluated by the rules engine against the ruleset.
  • modify: We can use this to either assign a value to a variable or a fact attribute; in our case we want to assign a status of Approved to the requestStatus property.
  • retract: This enables you to retract any of the facts matched in the pattern (for example, TLeaveRequest) so that it will no longer be evaluated as part of the ruleset.
  • call: This allows you to call a function to perform one or more actions.

The actions assert new and retract are important when we are dealing with rulesets that deal with multiple interdependent facts, as this allows us to control which facts are being evaluated by the rule engine at any particular time. Here, we are only dealing with a single fact, so we don't examine these constructs in this chapter, leaving them to Chapter 18, Using Business Rules to Implement Services.

For our purposes, we want to update the status of our leave, so select modify. Our rule should now look as shown in the following screenshot:

Creating the Then clause

The next step is to specify the fact to be modified. Click on the <target> element and you will be presented with a list of facts that are within scope. In our case, this will only be the TLeaveRequest that has just been matched by the IF clause, so select this. Our rule will now appear, as shown in the following screenshot:

Creating the Then clause

We now need to specify the properties we wish to modify, click on <add property> to open the Properties dialog. This will display a list of all the facts properties, allowing us to modify them as appropriate.

Select the Value cell for requestStatus. From here, you can directly enter a value, select a value from the drop-down list, or launch the expression builder. For our purposes, just enter the string Approved, as shown in the following screenshot, and then click Close.

Creating the Then clause

We don't need to specify values for any of the other properties, as the rules engine will only update those properties where a new value has been specified.

This completes the definition of our first rule. The next step is to wire it into our BPEL process.

Creating the Then clause

Creating the IF clause

For our leave approval rule, we need to define two tests, one to check that the request is only for a day in duration, which we can do by checking that the start date equals the end date, and the second to check that the request is of type Vacation.

To define the first test, click on <insert test>. This will add the line <operand> = = <operand> under the IF statement where we can define the test condition.

Creating the IF clause

Click on the first <operand>. This will display a drop-down list listing the valid facts and their attributes that we can test. From here, we can select the value to be tested, for example, TLeaveRequest.startDate in our case.

Creating the IF clause

Next from the operator drop-down list, select the test to be applied to the first operand (== in our case). We can either choose to compare it to a specified value or a second Operand. For our purpose, we want to check that the request.startDate equals the request.endDate, so click on the operand and select this from the drop-down list.

To create our second test, we follow pretty much the same process. This time we want to test that the operand leaveRequest.leaveType is equal to the value Vacation, so select the right-hand operator and type this in directly:

Creating the IF clause

Note, the rule editor has automatically inserted an and clause between our two tests. If you click on this, you have the option of changing this to an or clause.

Creating the Then clause

Now that we have defined our test, we need to define the action to take if the test evaluates to true. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out.

Creating the Then clause

The rule editor allows us to choose from the following action types:

  • assert new: We use this to create and assert a new fact, for example, a new LeaveRequest. Once asserted, the new fact will be evaluated by the rules engine against the ruleset.
  • modify: We can use this to either assign a value to a variable or a fact attribute; in our case we want to assign a status of Approved to the requestStatus property.
  • retract: This enables you to retract any of the facts matched in the pattern (for example, TLeaveRequest) so that it will no longer be evaluated as part of the ruleset.
  • call: This allows you to call a function to perform one or more actions.

The actions assert new and retract are important when we are dealing with rulesets that deal with multiple interdependent facts, as this allows us to control which facts are being evaluated by the rule engine at any particular time. Here, we are only dealing with a single fact, so we don't examine these constructs in this chapter, leaving them to Chapter 18, Using Business Rules to Implement Services.

For our purposes, we want to update the status of our leave, so select modify. Our rule should now look as shown in the following screenshot:

Creating the Then clause

The next step is to specify the fact to be modified. Click on the <target> element and you will be presented with a list of facts that are within scope. In our case, this will only be the TLeaveRequest that has just been matched by the IF clause, so select this. Our rule will now appear, as shown in the following screenshot:

Creating the Then clause

We now need to specify the properties we wish to modify, click on <add property> to open the Properties dialog. This will display a list of all the facts properties, allowing us to modify them as appropriate.

Select the Value cell for requestStatus. From here, you can directly enter a value, select a value from the drop-down list, or launch the expression builder. For our purposes, just enter the string Approved, as shown in the following screenshot, and then click Close.

Creating the Then clause

We don't need to specify values for any of the other properties, as the rules engine will only update those properties where a new value has been specified.

This completes the definition of our first rule. The next step is to wire it into our BPEL process.

Creating the Then clause

Creating the Then clause

Now that we have defined our test, we need to define the action to take if the test evaluates to true. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out.

Creating the Then clause

The rule editor allows us to choose from the following action types:

  • assert new: We use this to create and assert a new fact, for example, a new LeaveRequest. Once asserted, the new fact will be evaluated by the rules engine against the ruleset.
  • modify: We can use this to either assign a value to a variable or a fact attribute; in our case we want to assign a status of Approved to the requestStatus property.
  • retract: This enables you to retract any of the facts matched in the pattern (for example, TLeaveRequest) so that it will no longer be evaluated as part of the ruleset.
  • call: This allows you to call a function to perform one or more actions.

The actions assert new and retract are important when we are dealing with rulesets that deal with multiple interdependent facts, as this allows us to control which facts are being evaluated by the rule engine at any particular time. Here, we are only dealing with a single fact, so we don't examine these constructs in this chapter, leaving them to Chapter 18, Using Business Rules to Implement Services.

For our purposes, we want to update the status of our leave, so select modify. Our rule should now look as shown in the following screenshot:

Creating the Then clause

The next step is to specify the fact to be modified. Click on the <target> element and you will be presented with a list of facts that are within scope. In our case, this will only be the TLeaveRequest that has just been matched by the IF clause, so select this. Our rule will now appear, as shown in the following screenshot:

Creating the Then clause

We now need to specify the properties we wish to modify, click on <add property> to open the Properties dialog. This will display a list of all the facts properties, allowing us to modify them as appropriate.

Select the Value cell for requestStatus. From here, you can directly enter a value, select a value from the drop-down list, or launch the expression builder. For our purposes, just enter the string Approved, as shown in the following screenshot, and then click Close.

Creating the Then clause

We don't need to specify values for any of the other properties, as the rules engine will only update those properties where a new value has been specified.

This completes the definition of our first rule. The next step is to wire it into our BPEL process.

Creating the Then clause

Calling a business rule from BPEL

Save the rule, and then switch back to our composite and double-click the LeaveRequest BPEL process to edit it. Drag a Business Rule from the BPEL Activities and Components palette into your BPEL process (before the Human Task activity). This will open the Business Rule dialog (as shown in the following screenshot):

Calling a business rule from BPEL

First, we need to specify a name for the Business Rule activity within our BPEL process, so give it a meaningful name such as LeaveApprovalRules.

Next we need to specify the Business Rule Dictionary that we wish to use. If we click on the drop-down list, it will list all the dictionaries within our composite application, which in our case is LeaveApprovalRules that we have just defined.

Select this and the rule dialog will be updated (as shown in the following screenshot) to enable us to specify additional information about how we want to invoke the rule. First, we need to select the decision service that we want to invoke from BPEL. Our rule only contains a single decision service, LeaveApprovalDecisionService, so select it.

Once we've specified the service, we need to specify how we want to invoke the decision service. We specify this through the Operation attribute. Here we have two options:

  • Execute function and reset the session
  • Execute function

If we choose the option Execute function and thus don't reset the session, if we were then to call the decision service several times within the same instance of our BPEL process, each new invocation would reuse the same session and would also evaluate facts asserted in any previous invocation. For our purposes, we just need to assert a single fact and run the ruleset, so accept the default value of Execute function and reset the session(we will look at other modes of operation in more detail in Chapter 18, Using Business Rules to Implement Services).

Calling a business rule from BPEL

Assigning facts

The final step to invoke our business rules is to assign BPEL variables to the input and output facts. Click on the green plus symbol (as shown in the preceding screenshot), and this will launch the Decision Fact Map window, as shown in the following screenshot:

Assigning facts

At first glance, this looks like the standard Create Copy Operation window that we use when carrying out assigns within BPEL (which in reality is exactly what it is).

The key difference is that we are using this to assign values to the input facts to be submitted to the rules engines, so the Type on the To side of the copy operation is a Business Rule Facts.

The reverse is true for an output fact, where we use this dialog to map the output from the decision service back into a corresponding BPEL variable.

For our purpose, we just want to map the initial LeaveRequest in the process inputVariable into the corresponding fact, as shown in the preceding screenshot. Then we will map the output fact, which will contain our updated LeaveRequest back into our inputVariable.

Note

When JDeveloper opens the Decision Fact Map window, the Variables folder for the Business Rules Facts (circled in the preceding screenshot) is closed and it appears that there are no input facts. You must double-click on this to open it and expose the facts.

We have now wired the rule invocation into our BPEL process, before finally running our process; we need to modify our process to only invoke the workflow if the leave request hasn't been automatically approved.

To do this, just drag a switch onto your process, and then drag your workflow task into the first branch in the switch and define a test to check that the LeaveRequest hasn't been approved. You are now ready to deploy and run your modified process.

Assigning facts

The final step to invoke our business rules is to assign BPEL variables to the input and output facts. Click on the green plus symbol (as shown in the preceding screenshot), and this will launch the Decision Fact Map window, as shown in the following screenshot:

Assigning facts

At first glance, this looks like the standard Create Copy Operation window that we use when carrying out assigns within BPEL (which in reality is exactly what it is).

The key difference is that we are using this to assign values to the input facts to be submitted to the rules engines, so the Type on the To side of the copy operation is a Business Rule Facts.

The reverse is true for an output fact, where we use this dialog to map the output from the decision service back into a corresponding BPEL variable.

For our purpose, we just want to map the initial LeaveRequest in the process inputVariable into the corresponding fact, as shown in the preceding screenshot. Then we will map the output fact, which will contain our updated LeaveRequest back into our inputVariable.

Note

When JDeveloper opens the Decision Fact Map window, the Variables folder for the Business Rules Facts (circled in the preceding screenshot) is closed and it appears that there are no input facts. You must double-click on this to open it and expose the facts.

We have now wired the rule invocation into our BPEL process, before finally running our process; we need to modify our process to only invoke the workflow if the leave request hasn't been automatically approved.

To do this, just drag a switch onto your process, and then drag your workflow task into the first branch in the switch and define a test to check that the LeaveRequest hasn't been approved. You are now ready to deploy and run your modified process.

Using functions

Our current rule only approves vacations of one day in duration, requiring all other leave requests to be manually approved. Ideally, we would like to approve holidays of varying duration as long as sufficient notice has been given, for example:

  • Approve vacations of one day in duration with a start date that's two weeks or more in the future
  • Approve if for 2-3 days and more than 30 days in the future
  • Approve if 5 days or less and more than 60 days in the future
  • Approve if 10 days or less and more than 120 days in the future

To write these rules, we will need to calculate the duration of the leave period, as well as calculate how long it is before the start date. Out of the box, the rule engine provides the Duration extension methods, which allow us to calculate the number of days between two dates, but doesn't allow us to exclude weekends.

So we will need to write our own logic to calculate these values. Rather than embedding this logic directly in each rule, best practice dictates that we place this logic into a separate function. This not only ensures that we have a single version of the logic to implement but minimizes the size of our rules, thus making them simpler and easier to maintain. For our purposes, we will create the following functions:

  • startsIn: Which returns the number of days before the specified start date
  • leaveDuration: Which returns the number of days from the start date to the end date, excluding weekends

Creating a function

To create our first function, within the rule editor, click on the Functions tab. This will list all the functions currently defined to our ruleset. To create a new function, click on the green plus icon, as shown in the following screenshot:

Creating a function

This will add a new function with a default name (for example, Function_1) to our list. Click on the function name to select it and update it to startsIn. From the drop-down list, select the Return Type of the function, which is int in our case.

Next, we need to specify the arguments we wish to pass to our function. Click on the green plus sign, as shown in the following screenshot, and this will add an argument to our list. Here we can specify the argument name (for example, startDate), and from the drop-down list, the argument Type, which should be XMLGregorianCalendar (when creating XML facts, the JAXB processor maps the type xsd:date to javax.xml.datatype.XMLGregorianCalendar).

Note

The list of valid types is made up of the basic types (for example, int, double, char, and so on), plus the XML facts (excluding object factories) and the Java Facts (excluding the Rules Extension Method) defined in our rules dictionary.

Creating a function

The final step is to implement the business logic of our function, which consists of one or more actions. We enter these actions in the Body section of the function. The first action we need to create is one that creates a local variable of type calendar, which holds the current date.

To do this, click on <insert action> within the Body section of our function. The rule editor will display a drop-down list that lists all the available actions.

Creating a function

For our purpose, we want to create a new variable and assign a value to it, so select the assign new action, as shown in the preceding screenshot. This will insert a template for the assign new action into our function body (as shown in the following screenshot). We then configure the action by clicking on each part within the template and defining it as appropriate.

Creating a function

The first part we need to define is the type of variable we wish to create. Click on the <type> element within our <assign> statement, and the rule editor displays a drop-down list displaying all the available types. For our purposes, select Calendar.

Next, click on var. This will prompt us to enter the name of the variable that we want to create. Specify today, and hit enter.

Creating a function

Finally, we need to specify the value we want to initialize our variable with. Click on the <expression> element. The rule editor will display a drop-down box listing all the valid values we can assign to our variable, as shown in the following screenshot:

Creating a function

Select Calendar.getInstance(), which will initialize our variable to hold the current date.

For our second action, we want to calculate the number of days before the specified start date and place the result into the variable duration. To calculate this, we will make use of the Duration extension method provided with the rules engine.

We will do this by defining another assign new action in a similar way to the previous action. The key difference is how we specify the <expression>. This time, instead of selecting a value from the drop-down list, click on the Expression Builder icon (circled in the preceding screenshot) to launch the Expression Builder for the rules editor.

Creating a function

The Expression Builder provides a graphical tool for writing rule expressions and is accessed from various parts of the rule editor. It consists of the following areas:

  • Expression: The top textbox contains the rule expression that you are working on. You can either type data directly in here or use the Expression Builder to insert code fragments to build up the expression required.
  • Variables, Functions, Operators, Constants: This part of the Expression Builder lets you browse the various components that you can insert into your expression. Once you've located the component that you wish to use, click the Insert Into Expression button, and this will insert the appropriate code fragment into the expression.

    Note

    The code fragment is inserted at the point within the expression that the cursor is currently positioned.

  • Content Preview: This box displays a preview of the content that would be inserted into the expression if you clicked the Insert Into Expression button.

So let's use this to build our rules expression. The expression we want to build is a relatively simple one, namely:

Duration.days between(today,startDate) + 1

To build our expression, carry out the following steps. First, within the Functions tab, locate the function Duration.days between and insert this into the expression (as shown in the previous screenshot).

Next, within the Variables tab, locate the variable today. Then within the expression, highlight the first argument of the function (as shown in the following screenshot), and click Insert Into Expression.

Creating a function

This will update the value of the first argument to contain today; repeat this to update the second argument to contain startDate. Next, manually enter +1 to the end of the expression to complete it and click OK.

Finally add a third action to return the duration. The completed body of our function looks as shown in the following screenshot:

Creating a function

To implement our leaveDuration function, we follow the same approach (for details of this, see the code samples included with the book).

Testing a function

JDeveloper provides a test option that allows us to run a function in JDeveloper without the need to deploy it first. However, it will only allow us to run functions with no input parameters and returns a type of boolean.

In order to test our startsIn function, we need to write a wrapper function (for example, testStartsIn) which creates the required input parameters for our function, invokes it, and then prints out the result. So the body of our test function will look as shown in the following screenshot:

Testing a function

To run this, with the Functions tab, select the testStartsIn function, and click the Test button, as shown in the following screenshot:

Testing a function

Note

If there are any validation errors within our rules dictionary, then the Test button will be disabled.

This will execute the function and open a window displaying the result of the function and any output as shown in the following screenshot:

Testing a function

Testing decision service functions

We can also use this approach to test our decision service. The body for this test function appears as shown in the following screenshot:

Testing decision service functions

A couple of interesting points to note about this: the statement call RL.watch.all() will cause the function to output details about how the facts are being processed and which rules are being activated. This is something we cover in more detail in Chapter 18, Using Business Rules to Implement Services.

The other point to note is that the decision service return type is a result List, so we need to extract our fact from this list and cast it to the appropriate fact type in order to examine its content. We do this with the statement:

assign leaveRequest = (TLeaveRequest) resultList.get(0)

Invoking a function from within a rule

The final step is to invoke the functions as required from our ruleset. Before writing the additional rules for a vacation of less than 3, 5, and 10 days respectively, we will update our existing rule to use these new functions.

Go back to the One Day Vacation rule, and select the first test (so it has an orange box around it). Right-click and select Delete Test from the drop-down list, as shown in the following screenshot:

Invoking a function from within a rule

Next, click on <insert test> to add a new test to our IF clause. Click on the left operand. This time, instead of selecting an item from the drop-down list, click on the calculator icon to launch the Expression Builder and use it to build the expression:

startsIn(TLeaveRequest.startDate)

Set the value of the operator to >=. Finally, enter the value of 14 for the second operand. Follow the same approach to add another test to check that the leave duration is only one day. Our updated rule should now looks as shown in the following screenshot:

Invoking a function from within a rule

Once we have completed our test pattern, we can click validate just to check that its syntax is correct. Having completed this test, we can define similar approval rules for vacations of 3, 5, and 10 days respectively.

When completed, save your dictionary and rerun the leave approval process; you should now see that the vacations that match our leave approval rules are automatically approved.

Creating a function

To create our first function, within the rule editor, click on the Functions tab. This will list all the functions currently defined to our ruleset. To create a new function, click on the green plus icon, as shown in the following screenshot:

Creating a function

This will add a new function with a default name (for example, Function_1) to our list. Click on the function name to select it and update it to startsIn. From the drop-down list, select the Return Type of the function, which is int in our case.

Next, we need to specify the arguments we wish to pass to our function. Click on the green plus sign, as shown in the following screenshot, and this will add an argument to our list. Here we can specify the argument name (for example, startDate), and from the drop-down list, the argument Type, which should be XMLGregorianCalendar (when creating XML facts, the JAXB processor maps the type xsd:date to javax.xml.datatype.XMLGregorianCalendar).

Note

The list of valid types is made up of the basic types (for example, int, double, char, and so on), plus the XML facts (excluding object factories) and the Java Facts (excluding the Rules Extension Method) defined in our rules dictionary.

Creating a function

The final step is to implement the business logic of our function, which consists of one or more actions. We enter these actions in the Body section of the function. The first action we need to create is one that creates a local variable of type calendar, which holds the current date.

To do this, click on <insert action> within the Body section of our function. The rule editor will display a drop-down list that lists all the available actions.

Creating a function

For our purpose, we want to create a new variable and assign a value to it, so select the assign new action, as shown in the preceding screenshot. This will insert a template for the assign new action into our function body (as shown in the following screenshot). We then configure the action by clicking on each part within the template and defining it as appropriate.

Creating a function

The first part we need to define is the type of variable we wish to create. Click on the <type> element within our <assign> statement, and the rule editor displays a drop-down list displaying all the available types. For our purposes, select Calendar.

Next, click on var. This will prompt us to enter the name of the variable that we want to create. Specify today, and hit enter.

Creating a function

Finally, we need to specify the value we want to initialize our variable with. Click on the <expression> element. The rule editor will display a drop-down box listing all the valid values we can assign to our variable, as shown in the following screenshot:

Creating a function

Select Calendar.getInstance(), which will initialize our variable to hold the current date.

For our second action, we want to calculate the number of days before the specified start date and place the result into the variable duration. To calculate this, we will make use of the Duration extension method provided with the rules engine.

We will do this by defining another assign new action in a similar way to the previous action. The key difference is how we specify the <expression>. This time, instead of selecting a value from the drop-down list, click on the Expression Builder icon (circled in the preceding screenshot) to launch the Expression Builder for the rules editor.

Creating a function

The Expression Builder provides a graphical tool for writing rule expressions and is accessed from various parts of the rule editor. It consists of the following areas:

  • Expression: The top textbox contains the rule expression that you are working on. You can either type data directly in here or use the Expression Builder to insert code fragments to build up the expression required.
  • Variables, Functions, Operators, Constants: This part of the Expression Builder lets you browse the various components that you can insert into your expression. Once you've located the component that you wish to use, click the Insert Into Expression button, and this will insert the appropriate code fragment into the expression.

    Note

    The code fragment is inserted at the point within the expression that the cursor is currently positioned.

  • Content Preview: This box displays a preview of the content that would be inserted into the expression if you clicked the Insert Into Expression button.

So let's use this to build our rules expression. The expression we want to build is a relatively simple one, namely:

Duration.days between(today,startDate) + 1

To build our expression, carry out the following steps. First, within the Functions tab, locate the function Duration.days between and insert this into the expression (as shown in the previous screenshot).

Next, within the Variables tab, locate the variable today. Then within the expression, highlight the first argument of the function (as shown in the following screenshot), and click Insert Into Expression.

Creating a function

This will update the value of the first argument to contain today; repeat this to update the second argument to contain startDate. Next, manually enter +1 to the end of the expression to complete it and click OK.

Finally add a third action to return the duration. The completed body of our function looks as shown in the following screenshot:

Creating a function

To implement our leaveDuration function, we follow the same approach (for details of this, see the code samples included with the book).

Testing a function

JDeveloper provides a test option that allows us to run a function in JDeveloper without the need to deploy it first. However, it will only allow us to run functions with no input parameters and returns a type of boolean.

In order to test our startsIn function, we need to write a wrapper function (for example, testStartsIn) which creates the required input parameters for our function, invokes it, and then prints out the result. So the body of our test function will look as shown in the following screenshot:

Testing a function

To run this, with the Functions tab, select the testStartsIn function, and click the Test button, as shown in the following screenshot:

Testing a function

Note

If there are any validation errors within our rules dictionary, then the Test button will be disabled.

This will execute the function and open a window displaying the result of the function and any output as shown in the following screenshot:

Testing a function

Testing decision service functions

We can also use this approach to test our decision service. The body for this test function appears as shown in the following screenshot:

Testing decision service functions

A couple of interesting points to note about this: the statement call RL.watch.all() will cause the function to output details about how the facts are being processed and which rules are being activated. This is something we cover in more detail in Chapter 18, Using Business Rules to Implement Services.

The other point to note is that the decision service return type is a result List, so we need to extract our fact from this list and cast it to the appropriate fact type in order to examine its content. We do this with the statement:

assign leaveRequest = (TLeaveRequest) resultList.get(0)

Invoking a function from within a rule

The final step is to invoke the functions as required from our ruleset. Before writing the additional rules for a vacation of less than 3, 5, and 10 days respectively, we will update our existing rule to use these new functions.

Go back to the One Day Vacation rule, and select the first test (so it has an orange box around it). Right-click and select Delete Test from the drop-down list, as shown in the following screenshot:

Invoking a function from within a rule

Next, click on <insert test> to add a new test to our IF clause. Click on the left operand. This time, instead of selecting an item from the drop-down list, click on the calculator icon to launch the Expression Builder and use it to build the expression:

startsIn(TLeaveRequest.startDate)

Set the value of the operator to >=. Finally, enter the value of 14 for the second operand. Follow the same approach to add another test to check that the leave duration is only one day. Our updated rule should now looks as shown in the following screenshot:

Invoking a function from within a rule

Once we have completed our test pattern, we can click validate just to check that its syntax is correct. Having completed this test, we can define similar approval rules for vacations of 3, 5, and 10 days respectively.

When completed, save your dictionary and rerun the leave approval process; you should now see that the vacations that match our leave approval rules are automatically approved.

Testing a function

JDeveloper provides a test option that allows us to run a function in JDeveloper without the need to deploy it first. However, it will only allow us to run functions with no input parameters and returns a type of boolean.

In order to test our startsIn function, we need to write a wrapper function (for example, testStartsIn) which creates the required input parameters for our function, invokes it, and then prints out the result. So the body of our test function will look as shown in the following screenshot:

Testing a function

To run this, with the Functions tab, select the testStartsIn function, and click the Test button, as shown in the following screenshot:

Testing a function

Note

If there are any validation errors within our rules dictionary, then the Test button will be disabled.

This will execute the function and open a window displaying the result of the function and any output as shown in the following screenshot:

Testing a function

Testing decision service functions

We can also use this approach to test our decision service. The body for this test function appears as shown in the following screenshot:

Testing decision service functions

A couple of interesting points to note about this: the statement call RL.watch.all() will cause the function to output details about how the facts are being processed and which rules are being activated. This is something we cover in more detail in Chapter 18, Using Business Rules to Implement Services.

The other point to note is that the decision service return type is a result List, so we need to extract our fact from this list and cast it to the appropriate fact type in order to examine its content. We do this with the statement:

assign leaveRequest = (TLeaveRequest) resultList.get(0)

Invoking a function from within a rule

The final step is to invoke the functions as required from our ruleset. Before writing the additional rules for a vacation of less than 3, 5, and 10 days respectively, we will update our existing rule to use these new functions.

Go back to the One Day Vacation rule, and select the first test (so it has an orange box around it). Right-click and select Delete Test from the drop-down list, as shown in the following screenshot:

Invoking a function from within a rule

Next, click on <insert test> to add a new test to our IF clause. Click on the left operand. This time, instead of selecting an item from the drop-down list, click on the calculator icon to launch the Expression Builder and use it to build the expression:

startsIn(TLeaveRequest.startDate)

Set the value of the operator to >=. Finally, enter the value of 14 for the second operand. Follow the same approach to add another test to check that the leave duration is only one day. Our updated rule should now looks as shown in the following screenshot:

Invoking a function from within a rule

Once we have completed our test pattern, we can click validate just to check that its syntax is correct. Having completed this test, we can define similar approval rules for vacations of 3, 5, and 10 days respectively.

When completed, save your dictionary and rerun the leave approval process; you should now see that the vacations that match our leave approval rules are automatically approved.

Testing decision service functions

We can also use this approach to test our decision service. The body for this test function appears as shown in the following screenshot:

Testing decision service functions

A couple of interesting points to note about this: the statement call RL.watch.all() will cause the function to output details about how the facts are being processed and which rules are being activated. This is something we cover in more detail in Chapter 18, Using Business Rules to Implement Services.

The other point to note is that the decision service return type is a result List, so we need to extract our fact from this list and cast it to the appropriate fact type in order to examine its content. We do this with the statement:

assign leaveRequest = (TLeaveRequest) resultList.get(0)

Invoking a function from within a rule

The final step is to invoke the functions as required from our ruleset. Before writing the additional rules for a vacation of less than 3, 5, and 10 days respectively, we will update our existing rule to use these new functions.

Go back to the One Day Vacation rule, and select the first test (so it has an orange box around it). Right-click and select Delete Test from the drop-down list, as shown in the following screenshot:

Invoking a function from within a rule

Next, click on <insert test> to add a new test to our IF clause. Click on the left operand. This time, instead of selecting an item from the drop-down list, click on the calculator icon to launch the Expression Builder and use it to build the expression:

startsIn(TLeaveRequest.startDate)

Set the value of the operator to >=. Finally, enter the value of 14 for the second operand. Follow the same approach to add another test to check that the leave duration is only one day. Our updated rule should now looks as shown in the following screenshot:

Invoking a function from within a rule

Once we have completed our test pattern, we can click validate just to check that its syntax is correct. Having completed this test, we can define similar approval rules for vacations of 3, 5, and 10 days respectively.

When completed, save your dictionary and rerun the leave approval process; you should now see that the vacations that match our leave approval rules are automatically approved.

Invoking a function from within a rule

The final step is to invoke the functions as required from our ruleset. Before writing the additional rules for a vacation of less than 3, 5, and 10 days respectively, we will update our existing rule to use these new functions.

Go back to the One Day Vacation rule, and select the first test (so it has an orange box around it). Right-click and select Delete Test from the drop-down list, as shown in the following screenshot:

Invoking a function from within a rule

Next, click on <insert test> to add a new test to our IF clause. Click on the left operand. This time, instead of selecting an item from the drop-down list, click on the calculator icon to launch the Expression Builder and use it to build the expression:

startsIn(TLeaveRequest.startDate)

Set the value of the operator to >=. Finally, enter the value of 14 for the second operand. Follow the same approach to add another test to check that the leave duration is only one day. Our updated rule should now looks as shown in the following screenshot:

Invoking a function from within a rule

Once we have completed our test pattern, we can click validate just to check that its syntax is correct. Having completed this test, we can define similar approval rules for vacations of 3, 5, and 10 days respectively.

When completed, save your dictionary and rerun the leave approval process; you should now see that the vacations that match our leave approval rules are automatically approved.

Using decision tables

Our updated ruleset consists of four rules that are very repetitive in nature. It would make more sense to specify the rule just once and then parameterize it in a tabular fashion. This is effectively what decision tables allow you to do.

Note

Before creating your decision table, you will need to delete the rules we have just defined, otherwise we will end up with two versions of the same rules within our ruleset.

Defining a bucket set

When creating a decision table, you are often required to specify a list of values or a range of values that apply to a particular rule. For example, in the case of our vacation approval rule, we will need to specify the following ranges of leave duration values that we are interested in:

  • 1 day
  • 2-3 days
  • 4-5 days
  • 6-10 days

We define these in a bucketset. To do this, select the Bucketsets tab in the rule editor, then click on the green plus symbol and select List of Ranges from the drop-down list, as shown in the following screenshot:

Defining a bucket set

This will create a new bucketset called Buckset_1. Click on the name and change it to something more meaningful such as LeaveDuration. By default, the bucketset will have a Datatype of int, which is fine for our purposes.

Click on the pencil icon. This will launch the Edit Bucketset - LeaveDuration window, as shown in the following screenshot:

Defining a bucket set

A bucketset, as its name implies, consists of one or more buckets, each corresponding to a range of values. For each bucket, you specify its Endpoint and whether the endpoint is included within the bucket. The range of values covered by a bucket is from the endpoint of the bucket to the endpoint of the next bucket.

You can also choose whether to include the specified endpoint in its corresponding bucket. If you don't, then the endpoint will be included in the preceding bucket.

For example, in the preceding screenshot, the second bucket (with the endpoint of 5) covers the integer values from 6 (as the endpoint 5 isn't included in the bucket) to 10 (the end point of the next bucket).

It is good practice to specify a meaningful alias for each bucket, as when you reference a bucket in a decision table, you do so using its alias. If you don't specify an alias, then it will default to the description in the Range.

In preparation for defining our decision table, we have defined two bucketsets: LeaveDuration, as shown in the preceding screenshot, and StartsIn.

Creating a decision table

To create a decision table, select the Employee Leave Approval ruleset tab. Click on the green plus icon and select Create Decision Table, as shown in the following screenshot:

Creating a decision table

This will add an empty decision table to our ruleset, as shown in the following screenshot:

Creating a decision table

The decision table consists of three areas: the first is for defining our tests (or conditions), the second is for conflict resolution (for resolving overlapping rules within our decision table), and the final area is for defining our actions.

Click on <insert condition>. This will add an empty condition with the name C1 to our ruleset. At the same time, the rule editor will also add an additional column to our decision table. This represents our first rule and is given the name R1. To specify the condition that we want to test, double-click on C1. This will bring up a drop-down list (similar to the one used to define an operand within the test part of a rule), as shown in the following screenshot:

Creating a decision table

As with our original rule, the first condition we want to test is the type of leave request, so select TLeaveRequest.leaveType from the drop-down list.

For our first rule, we want to check that the leave request is of type Vacation, so click on the appropriate cell (the intersection of C1 and R1). The rule editor will present us with a drop-down listing our options. In this case, directly enter Vacation, as shown in the following screenshot:

Creating a decision table

The next step is to add a second condition to test the leave duration. To do this, click on the green plus icon and select Conditions. This will add another condition row to our decision table. Click on <edit condition> and use the expression builder to define the following:

leaveDuration(TLeaveRequest.startDate, TLeaveRequest.endDate)

For each rule, we need to test the result of this function against the appropriate value in our LeaveDuration bucketset. Before we can do this, we must first associate the condition with that bucketset. To do this, ensure that the condition cell is selected and then click on the drop-down list above it and select LeaveDuration, as shown in the following screenshot:

Creating a decision table

The next step is to check that the leave duration is one day, so click on the appropriate cell (the intersection of C2 and R1). The rule editor will present us with a drop-down listing our options, which will be the list of buckets in the LeaveDuration bucketset. From here, select the option 1 day.

Creating a decision table

Add three more rules to our decision table (to add a rule, click on the green plus icon and select Rule). For R2, specify a leave duration of 2..3 days, for R3 4..5 days, and R4 6..10 days.

For each of these rules, we want to check that the leave type is Vacation. Rather than specifying this individually for each rule (which we could do), we can merge these into a single cell and specify the test just once. To do this, select each cell (hold down the Ctrl key while you do this) and then right-click. From the drop-down list, select Merge Selected Cells.

Creating a decision table

Next, we need to add the final condition as follows:

startsIn(TLeaveRequest.startDate)

To check whether sufficient notice has been given to automatically approve the vacation request, add this in the normal way and associate the condition with the StartsIn bucketset.

For our first rule, we want to approve the leave request if it starts in 14 or more days time, so select ALL the appropriate buckets from our bucketset (as shown in the following screenshot). Complete the test for rules R2, R3, and R4.

Creating a decision table

The final step is to specify the action we want to take for each of our rules. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out. Select Modify. This will insert a modify action into our decision table; double-click on this to open the Action Editor (as shown in the following screenshot):

Creating a decision table

The Form option allows us to select from the drop-down list which action we want to perform. For the Modify action, we first need to specify the fact we wish to update, so select TLeaveRequest in the Target section.

The Arguments section will then be populated to list all the properties for the selected fact. Select requestStatus and enter a value of Approved. Also select the cell to be parameterized. If you don't specify this, then it forces every rule within our decision table to use the same value.

Finally, ensure that the checkbox Always Selected is unchecked (we will see why in a moment) and click OK. This will return us to our decision table, as shown in the following screenshot:

Creating a decision table

At this point, the action will contain an identical configuration for each rule, which we can then modify as appropriate.

Each rule has an associated checkbox for the action, which, by default, is unchecked. This specifies whether that action should be taken for that rule. In our case, we want each rule to update the request status, so ensure that the checkbox is selected for every rule (as shown in the preceding screenshot).

Note

If you had checked the Always Selected checkbox in the Action Editor, then the action would be selected for each rule and would also be read-only to prevent you from modifying it.

The action will also contain a row for every property that we are modifying, which, in our example, is just one (requestStatus). As we selected this property to be parameterized, we could override the specified value for each individual rule.

Conflict resolution

This almost completes our decision table. However, we will add one more rule to handle any other scenario that isn't covered by our current ruleset. Add one more rule, but don't specify any values for any of the conditions, so the rule will apply to everything. In the actions section, specify a value of Manual to indicate that the request requires manual approval.

Upon doing this, the rule editor will add a row to the conflicts section of the decision table, as shown in the following screenshot:

Conflict resolution

This is indicating that R5 is in conflict with R1, R2, R3, and R4, that is, that they both apply to the same scenario. Double-click on the conflict warning for R1, and this will launch the Conflict Resolution window, as shown in the following screenshot:

Conflict resolution

Here, we can specify how we wish to handle the conflict. Click on the drop-down list and select Override to specify that R1 takes precedence over R5. Do the same for rules R2, R3, and R4. The decision table will be updated to show no conflicts and that rules R1 to R4 override R5.

This completes our decision table, so save the rules dictionary and redeploy the leave approval composite to test it.

Defining a bucket set

When creating a decision table, you are often required to specify a list of values or a range of values that apply to a particular rule. For example, in the case of our vacation approval rule, we will need to specify the following ranges of leave duration values that we are interested in:

  • 1 day
  • 2-3 days
  • 4-5 days
  • 6-10 days

We define these in a bucketset. To do this, select the Bucketsets tab in the rule editor, then click on the green plus symbol and select List of Ranges from the drop-down list, as shown in the following screenshot:

Defining a bucket set

This will create a new bucketset called Buckset_1. Click on the name and change it to something more meaningful such as LeaveDuration. By default, the bucketset will have a Datatype of int, which is fine for our purposes.

Click on the pencil icon. This will launch the Edit Bucketset - LeaveDuration window, as shown in the following screenshot:

Defining a bucket set

A bucketset, as its name implies, consists of one or more buckets, each corresponding to a range of values. For each bucket, you specify its Endpoint and whether the endpoint is included within the bucket. The range of values covered by a bucket is from the endpoint of the bucket to the endpoint of the next bucket.

You can also choose whether to include the specified endpoint in its corresponding bucket. If you don't, then the endpoint will be included in the preceding bucket.

For example, in the preceding screenshot, the second bucket (with the endpoint of 5) covers the integer values from 6 (as the endpoint 5 isn't included in the bucket) to 10 (the end point of the next bucket).

It is good practice to specify a meaningful alias for each bucket, as when you reference a bucket in a decision table, you do so using its alias. If you don't specify an alias, then it will default to the description in the Range.

In preparation for defining our decision table, we have defined two bucketsets: LeaveDuration, as shown in the preceding screenshot, and StartsIn.

Creating a decision table

To create a decision table, select the Employee Leave Approval ruleset tab. Click on the green plus icon and select Create Decision Table, as shown in the following screenshot:

Creating a decision table

This will add an empty decision table to our ruleset, as shown in the following screenshot:

Creating a decision table

The decision table consists of three areas: the first is for defining our tests (or conditions), the second is for conflict resolution (for resolving overlapping rules within our decision table), and the final area is for defining our actions.

Click on <insert condition>. This will add an empty condition with the name C1 to our ruleset. At the same time, the rule editor will also add an additional column to our decision table. This represents our first rule and is given the name R1. To specify the condition that we want to test, double-click on C1. This will bring up a drop-down list (similar to the one used to define an operand within the test part of a rule), as shown in the following screenshot:

Creating a decision table

As with our original rule, the first condition we want to test is the type of leave request, so select TLeaveRequest.leaveType from the drop-down list.

For our first rule, we want to check that the leave request is of type Vacation, so click on the appropriate cell (the intersection of C1 and R1). The rule editor will present us with a drop-down listing our options. In this case, directly enter Vacation, as shown in the following screenshot:

Creating a decision table

The next step is to add a second condition to test the leave duration. To do this, click on the green plus icon and select Conditions. This will add another condition row to our decision table. Click on <edit condition> and use the expression builder to define the following:

leaveDuration(TLeaveRequest.startDate, TLeaveRequest.endDate)

For each rule, we need to test the result of this function against the appropriate value in our LeaveDuration bucketset. Before we can do this, we must first associate the condition with that bucketset. To do this, ensure that the condition cell is selected and then click on the drop-down list above it and select LeaveDuration, as shown in the following screenshot:

Creating a decision table

The next step is to check that the leave duration is one day, so click on the appropriate cell (the intersection of C2 and R1). The rule editor will present us with a drop-down listing our options, which will be the list of buckets in the LeaveDuration bucketset. From here, select the option 1 day.

Creating a decision table

Add three more rules to our decision table (to add a rule, click on the green plus icon and select Rule). For R2, specify a leave duration of 2..3 days, for R3 4..5 days, and R4 6..10 days.

For each of these rules, we want to check that the leave type is Vacation. Rather than specifying this individually for each rule (which we could do), we can merge these into a single cell and specify the test just once. To do this, select each cell (hold down the Ctrl key while you do this) and then right-click. From the drop-down list, select Merge Selected Cells.

Creating a decision table

Next, we need to add the final condition as follows:

startsIn(TLeaveRequest.startDate)

To check whether sufficient notice has been given to automatically approve the vacation request, add this in the normal way and associate the condition with the StartsIn bucketset.

For our first rule, we want to approve the leave request if it starts in 14 or more days time, so select ALL the appropriate buckets from our bucketset (as shown in the following screenshot). Complete the test for rules R2, R3, and R4.

Creating a decision table

The final step is to specify the action we want to take for each of our rules. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out. Select Modify. This will insert a modify action into our decision table; double-click on this to open the Action Editor (as shown in the following screenshot):

Creating a decision table

The Form option allows us to select from the drop-down list which action we want to perform. For the Modify action, we first need to specify the fact we wish to update, so select TLeaveRequest in the Target section.

The Arguments section will then be populated to list all the properties for the selected fact. Select requestStatus and enter a value of Approved. Also select the cell to be parameterized. If you don't specify this, then it forces every rule within our decision table to use the same value.

Finally, ensure that the checkbox Always Selected is unchecked (we will see why in a moment) and click OK. This will return us to our decision table, as shown in the following screenshot:

Creating a decision table

At this point, the action will contain an identical configuration for each rule, which we can then modify as appropriate.

Each rule has an associated checkbox for the action, which, by default, is unchecked. This specifies whether that action should be taken for that rule. In our case, we want each rule to update the request status, so ensure that the checkbox is selected for every rule (as shown in the preceding screenshot).

Note

If you had checked the Always Selected checkbox in the Action Editor, then the action would be selected for each rule and would also be read-only to prevent you from modifying it.

The action will also contain a row for every property that we are modifying, which, in our example, is just one (requestStatus). As we selected this property to be parameterized, we could override the specified value for each individual rule.

Conflict resolution

This almost completes our decision table. However, we will add one more rule to handle any other scenario that isn't covered by our current ruleset. Add one more rule, but don't specify any values for any of the conditions, so the rule will apply to everything. In the actions section, specify a value of Manual to indicate that the request requires manual approval.

Upon doing this, the rule editor will add a row to the conflicts section of the decision table, as shown in the following screenshot:

Conflict resolution

This is indicating that R5 is in conflict with R1, R2, R3, and R4, that is, that they both apply to the same scenario. Double-click on the conflict warning for R1, and this will launch the Conflict Resolution window, as shown in the following screenshot:

Conflict resolution

Here, we can specify how we wish to handle the conflict. Click on the drop-down list and select Override to specify that R1 takes precedence over R5. Do the same for rules R2, R3, and R4. The decision table will be updated to show no conflicts and that rules R1 to R4 override R5.

This completes our decision table, so save the rules dictionary and redeploy the leave approval composite to test it.

Creating a decision table

To create a decision table, select the Employee Leave Approval ruleset tab. Click on the green plus icon and select Create Decision Table, as shown in the following screenshot:

Creating a decision table

This will add an empty decision table to our ruleset, as shown in the following screenshot:

Creating a decision table

The decision table consists of three areas: the first is for defining our tests (or conditions), the second is for conflict resolution (for resolving overlapping rules within our decision table), and the final area is for defining our actions.

Click on <insert condition>. This will add an empty condition with the name C1 to our ruleset. At the same time, the rule editor will also add an additional column to our decision table. This represents our first rule and is given the name R1. To specify the condition that we want to test, double-click on C1. This will bring up a drop-down list (similar to the one used to define an operand within the test part of a rule), as shown in the following screenshot:

Creating a decision table

As with our original rule, the first condition we want to test is the type of leave request, so select TLeaveRequest.leaveType from the drop-down list.

For our first rule, we want to check that the leave request is of type Vacation, so click on the appropriate cell (the intersection of C1 and R1). The rule editor will present us with a drop-down listing our options. In this case, directly enter Vacation, as shown in the following screenshot:

Creating a decision table

The next step is to add a second condition to test the leave duration. To do this, click on the green plus icon and select Conditions. This will add another condition row to our decision table. Click on <edit condition> and use the expression builder to define the following:

leaveDuration(TLeaveRequest.startDate, TLeaveRequest.endDate)

For each rule, we need to test the result of this function against the appropriate value in our LeaveDuration bucketset. Before we can do this, we must first associate the condition with that bucketset. To do this, ensure that the condition cell is selected and then click on the drop-down list above it and select LeaveDuration, as shown in the following screenshot:

Creating a decision table

The next step is to check that the leave duration is one day, so click on the appropriate cell (the intersection of C2 and R1). The rule editor will present us with a drop-down listing our options, which will be the list of buckets in the LeaveDuration bucketset. From here, select the option 1 day.

Creating a decision table

Add three more rules to our decision table (to add a rule, click on the green plus icon and select Rule). For R2, specify a leave duration of 2..3 days, for R3 4..5 days, and R4 6..10 days.

For each of these rules, we want to check that the leave type is Vacation. Rather than specifying this individually for each rule (which we could do), we can merge these into a single cell and specify the test just once. To do this, select each cell (hold down the Ctrl key while you do this) and then right-click. From the drop-down list, select Merge Selected Cells.

Creating a decision table

Next, we need to add the final condition as follows:

startsIn(TLeaveRequest.startDate)

To check whether sufficient notice has been given to automatically approve the vacation request, add this in the normal way and associate the condition with the StartsIn bucketset.

For our first rule, we want to approve the leave request if it starts in 14 or more days time, so select ALL the appropriate buckets from our bucketset (as shown in the following screenshot). Complete the test for rules R2, R3, and R4.

Creating a decision table

The final step is to specify the action we want to take for each of our rules. Click on <insert action>. This will display a drop-down list where you need to specify the Action Type you wish to carry out. Select Modify. This will insert a modify action into our decision table; double-click on this to open the Action Editor (as shown in the following screenshot):

Creating a decision table

The Form option allows us to select from the drop-down list which action we want to perform. For the Modify action, we first need to specify the fact we wish to update, so select TLeaveRequest in the Target section.

The Arguments section will then be populated to list all the properties for the selected fact. Select requestStatus and enter a value of Approved. Also select the cell to be parameterized. If you don't specify this, then it forces every rule within our decision table to use the same value.

Finally, ensure that the checkbox Always Selected is unchecked (we will see why in a moment) and click OK. This will return us to our decision table, as shown in the following screenshot:

Creating a decision table

At this point, the action will contain an identical configuration for each rule, which we can then modify as appropriate.

Each rule has an associated checkbox for the action, which, by default, is unchecked. This specifies whether that action should be taken for that rule. In our case, we want each rule to update the request status, so ensure that the checkbox is selected for every rule (as shown in the preceding screenshot).

Note

If you had checked the Always Selected checkbox in the Action Editor, then the action would be selected for each rule and would also be read-only to prevent you from modifying it.

The action will also contain a row for every property that we are modifying, which, in our example, is just one (requestStatus). As we selected this property to be parameterized, we could override the specified value for each individual rule.

Conflict resolution

This almost completes our decision table. However, we will add one more rule to handle any other scenario that isn't covered by our current ruleset. Add one more rule, but don't specify any values for any of the conditions, so the rule will apply to everything. In the actions section, specify a value of Manual to indicate that the request requires manual approval.

Upon doing this, the rule editor will add a row to the conflicts section of the decision table, as shown in the following screenshot:

Conflict resolution

This is indicating that R5 is in conflict with R1, R2, R3, and R4, that is, that they both apply to the same scenario. Double-click on the conflict warning for R1, and this will launch the Conflict Resolution window, as shown in the following screenshot:

Conflict resolution

Here, we can specify how we wish to handle the conflict. Click on the drop-down list and select Override to specify that R1 takes precedence over R5. Do the same for rules R2, R3, and R4. The decision table will be updated to show no conflicts and that rules R1 to R4 override R5.

This completes our decision table, so save the rules dictionary and redeploy the leave approval composite to test it.

Conflict resolution

This almost completes our decision table. However, we will add one more rule to handle any other scenario that isn't covered by our current ruleset. Add one more rule, but don't specify any values for any of the conditions, so the rule will apply to everything. In the actions section, specify a value of Manual to indicate that the request requires manual approval.

Upon doing this, the rule editor will add a row to the conflicts section of the decision table, as shown in the following screenshot:

Conflict resolution

This is indicating that R5 is in conflict with R1, R2, R3, and R4, that is, that they both apply to the same scenario. Double-click on the conflict warning for R1, and this will launch the Conflict Resolution window, as shown in the following screenshot:

Conflict resolution

Here, we can specify how we wish to handle the conflict. Click on the drop-down list and select Override to specify that R1 takes precedence over R5. Do the same for rules R2, R3, and R4. The decision table will be updated to show no conflicts and that rules R1 to R4 override R5.

This completes our decision table, so save the rules dictionary and redeploy the leave approval composite to test it.

Summary

Business rules are a key component of any application. Traditionally, these rules are buried deep within the code of an application, making them very difficult to change.

Yet, in a typical application, it is the business rules that change most frequently, by separating these out as a specialized service, it allows us to change these rules without having to modify the overall application.

In this chapter, we have looked at how we can use the Oracle Business Rules engine to implement such rules, and how we can invoke these from within BPEL as a decision service.

It's worth noting that you are not restricted to calling these rules from just BPEL, as the rules engine comes with a Java API that allows it to be easily invoked from any Java application, or alternatively, you can expose the rules as web services, which can then be invoked from any web service client.

Finally, while in this chapter, we have only looked at very simple rules. The Oracle Business Rules engine implements the industry standard Rete Algorithm, making it ideal for evaluating a large number of interdependent rules and facts. We examine some of these capabilities in more detail in Chapter 18, Using Business Rules to Implement Services.

You have been reading a chapter from
Oracle SOA Suite 11g R1 Developer's Guide
Published in: Jul 2010
Publisher: Packt
ISBN-13: 9781849680189
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime