7.5. Pricing example decisions (decision tables)
The Pricing example decision set demonstrates how to use a spreadsheet decision table for calculating the retail cost of an insurance policy in tabular format instead of directly in a DRL file.
The following is an overview of the Pricing example:
-
Name:
decisiontable
-
Main class:
org.drools.examples.decisiontable.PricingRuleDTExample
(insrc/main/java
) -
Module:
drools-examples
- Type: Java application
-
Rule file:
org.drools.examples.decisiontable.ExamplePolicyPricing.xls
(insrc/main/resources
) - Objective: Demonstrates use of spreadsheet decision tables to define rules
Spreadsheet decision tables are XLS or XLSX spreadsheets that contain business rules defined in a tabular format. You can include spreadsheet decision tables with standalone Red Hat Decision Manager projects or upload them to projects in Business Central. Each row in a decision table is a rule, and each column is a condition, an action, or another rule attribute. After you create and upload your decision tables into your Red Hat Decision Manager project, the rules you defined are compiled into Drools Rule Language (DRL) rules as with all other rule assets.
The purpose of the Pricing example is to provide a set of business rules to calculate the base price and a discount for a car driver applying for a specific type of insurance policy. The driver’s age and history and the policy type all contribute to calculate the basic premium, and additional rules calculate potential discounts for which the driver might be eligible.
To execute the example, run the org.drools.examples.decisiontable.PricingRuleDTExample
class as a Java application in your IDE.
After the execution, the following output appears in the IDE console window:
Cheapest possible BASE PRICE IS: 120 DISCOUNT IS: 20
The code to execute the example follows the typical execution pattern: the rules are loaded, the facts are inserted, and a stateless KIE session is created. The difference in this example is that the rules are defined in an ExamplePolicyPricing.xls
file instead of a DRL file or other source. The spreadsheet file is loaded into the decision engine using templates and DRL rules.
Spreadsheet decision table setup
The ExamplePolicyPricing.xls
spreadsheet contains two decision tables in the first tab:
-
Base pricing rules
-
Promotional discount rules
As the example spreadsheet demonstrates, you can use only the first tab of a spreadsheet to create decision tables, but multiple tables can be within a single tab. Decision tables do not necessarily follow top-down logic, but are more of a means to capture data resulting in rules. The evaluation of the rules is not necessarily in the given order, because all of the normal mechanics of the decision engine still apply. This is why you can have multiple decision tables in the same tab of a spreadsheet.
The decision tables are executed through the corresponding rule template files BasePricing.drt
and PromotionalPricing.drt
. These template files reference the decision tables through their template parameter and directly reference the various headers for the conditions and actions in the decision tables.
BasePricing.drt rule template file
template header age[] profile priorClaims policyType base reason package org.drools.examples.decisiontable; template "Pricing bracket" age policyType base rule "Pricing bracket_@{row.rowNumber}" when Driver(age >= @{age0}, age <= @{age1} , priorClaims == "@{priorClaims}" , locationRiskProfile == "@{profile}" ) policy: Policy(type == "@{policyType}") then policy.setBasePrice(@{base}); System.out.println("@{reason}"); end end template
PromotionalPricing.drt rule template file
template header age[] priorClaims policyType discount package org.drools.examples.decisiontable; template "discounts" age priorClaims policyType discount rule "Discounts_@{row.rowNumber}" when Driver(age >= @{age0}, age <= @{age1}, priorClaims == "@{priorClaims}") policy: Policy(type == "@{policyType}") then policy.applyDiscount(@{discount}); end end template
The rules are executed through the kmodule.xml
reference of the KIE Session DTableWithTemplateKB
, which specifically mentions the ExamplePolicyPricing.xls
spreadsheet and is required for successful execution of the rules. This execution method enables you to execute the rules as a standalone unit (as in this example) or to include the rules in a packaged knowledge JAR (KJAR) file, so that the spreadsheet is packaged along with the rules for execution.
The following section of the kmodule.xml
file is required for the execution of the rules and spreadsheet to work successfully:
<kbase name="DecisionTableKB" packages="org.drools.examples.decisiontable"> <ksession name="DecisionTableKS" type="stateless"/> </kbase> <kbase name="DTableWithTemplateKB" packages="org.drools.examples.decisiontable-template"> <ruleTemplate dtable="org/drools/examples/decisiontable-template/ExamplePolicyPricingTemplateData.xls" template="org/drools/examples/decisiontable-template/BasePricing.drt" row="3" col="3"/> <ruleTemplate dtable="org/drools/examples/decisiontable-template/ExamplePolicyPricingTemplateData.xls" template="org/drools/examples/decisiontable-template/PromotionalPricing.drt" row="18" col="3"/> <ksession name="DTableWithTemplateKS"/> </kbase>
As an alternative to executing the decision tables using rule template files, you can use the DecisionTableConfiguration
object and specify an input spreadsheet as the input type, such as DecisionTableInputType.xls
:
DecisionTableConfiguration dtableconfiguration = KnowledgeBuilderFactory.newDecisionTableConfiguration(); dtableconfiguration.setInputType( DecisionTableInputType.XLS ); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); Resource xlsRes = ResourceFactory.newClassPathResource( "ExamplePolicyPricing.xls", getClass() ); kbuilder.add( xlsRes, ResourceType.DTABLE, dtableconfiguration );
The Pricing example uses two fact types:
-
Driver
-
Policy
.
The example sets the default values for both facts in their respective Java classes Driver.java
and Policy.java
. The Driver
is 30 years old, has had no prior claims, and currently has a risk profile of LOW
. The Policy
that the driver is applying for is COMPREHENSIVE
.
In any decision table, each row is considered a different rule and each column is a condition or an action. Each row is evaluated in a decision table unless the agenda is cleared upon execution.
Decision table spreadsheets (XLS or XLSX) require two key areas that define rule data:
-
A
RuleSet
area -
A
RuleTable
area
The RuleSet
area of the spreadsheet defines elements that you want to apply globally to all rules in the same package (not only the spreadsheet), such as a rule set name or universal rule attributes. The RuleTable
area defines the actual rules (rows) and the conditions, actions, and other rule attributes (columns) that constitute that rule table within the specified rule set. A decision table spreadsheet can contain multiple RuleTable
areas, but only one RuleSet
area.
図7.11 Decision table configuration
The RuleTable
area also defines the objects to which the rule attributes apply, in this case Driver
and Policy
, followed by constraints on the objects. For example, the Driver
object constraint that defines the Age Bracket
column is age >= $1, age <= $2
, where the comma-separated range is defined in the table column values, such as 18,24
.
Base pricing rules
The Base pricing rules
decision table in the Pricing example evaluates the age, risk profile, number of claims, and policy type of the driver and produces the base price of the policy based on these conditions.
図7.12 Base price calculation
The Driver
attributes are defined in the following table columns:
-
Age Bracket
: The age bracket has a definition for the conditionage >=$1, age <=$2
, which defines the condition boundaries for the driver’s age. This condition column highlights the use of$1 and $2
, which is comma delimited in the spreadsheet. You can write these values as18,24
or18, 24
and both formats work in the execution of the business rules. -
Location risk profile
: The risk profile is a string that the example program passes always asLOW
but can be changed to reflectMED
orHIGH
. -
Number of prior claims
: The number of claims is defined as an integer that the condition column must exactly equal to trigger the action. The value is not a range, only exact matches.
The Policy
of the decision table is used in both the conditions and the actions of the rule and has attributes defined in the following table columns:
-
Policy type applying for
: The policy type is a condition that is passed as a string that defines the type of coverage:COMPREHENSIVE
,FIRE_THEFT
, orTHIRD_PARTY
. -
Base $ AUD
: ThebasePrice
is defined as anACTION
that sets the price through the constraintpolicy.setBasePrice($param);
based on the spreadsheet cells corresponding to this value. When you execute the corresponding DRL rule for this decision table, thethen
portion of the rule executes this action statement on the true conditions matching the facts and sets the base price to the corresponding value. -
Record Reason
: When the rule successfully executes, this action generates an output message to theSystem.out
console reflecting which rule fired. This is later captured in the application and printed.
The example also uses the first column on the left to categorize rules. This column is for annotation only and has no affect on rule execution.
Promotional discount rules
The Promotional discount rules
decision table in the Pricing example evaluates the age, number of prior claims, and policy type of the driver to generate a potential discount on the price of the insurance policy.
図7.13 Discount calculation
This decision table contains the conditions for the discount for which the driver might be eligible. Similar to the base price calculation, this table evaluates the Age
, Number of prior claims
of the driver, and the Policy type applying for
to determine a Discount %
rate to be applied. For example, if the driver is 30 years old, has no prior claims, and is applying for a COMPREHENSIVE
policy, the driver is given a discount of 20
percent.