Chapter 5. Decision Tables
5.1. Decision Tables
5.2. Decision Tables in Spreadsheets
5.3. Open Office Example

Figure 5.1. Open Office Screenshot
Note
5.4. Rules and Spreadsheets
- Rules inserted into rows
- As each row is a rule, the same principles apply as with written code. As the rule engine processes the facts, any rules that match may fire.
- Agendas
- It is possible to clear the agenda when a rule fires and simulate a very simple decision table where only the first match effects an action.
- Multiple tables
- You can have multiple tables on one spreadsheet. This way, rules can be grouped where they share common templates, but are still all combined into one rule package.
5.5. The RuleTable Keyword
Important
5.6. The RuleSet Keyword
5.7. Rule Template Example

Figure 5.2. Rule Template
- The RuleSet keyword indicates the name to be used in the rule package that will encompass all the rules. This name is optional, using a default, but it must have the RuleSet keyword in the cell immediately to the right. The other keywords visible in Column C are Import and Sequential.
- After the RuleTable keyword there is a name, used to prefix the names of the generated rules. The row numbers are appended to guarantee unique rule names.
- The column of RuleTable indicates the column in which the rules start; columns to the left are ignored.
- Referring to row 14 (the row immediately after RuleTable), the keywords CONDITION and ACTION indicate that the data in the columns below are for either the LHS or the RHS parts of a rule. There are other attributes on the rule which can also be optionally set this way.
- Row 15 contains declarations of ObjectTypes. The content in this row is optional, but if this option is not in use, the row must be left blank. When using this row, the values in the cells below (row 16) become constraints on that object type. In the above case, it generates
Person(age=="42")andCheese(type=="stilton"), where 42 and "stilton" come from row 18. In the above example, the "==" is implicit. If just a field name is given, the translator assumes that it is to generate an exact match. - Row 16 contains the rule templates themselves. They can use the "$param" placeholder to indicate where data from the cells below should be interpolated. (For multiple insertions, use "$1", "$2", etc., indicating parameters from a comma-separated list in a cell below.) Row 17 is ignored. It may contain textual descriptions of the column's purpose.
- Rows 18 and 19 show data, which will be combined (interpolated) with the templates in row 15, to generate rules. If a cell contains no data, then its template is ignored. (This would mean that some condition or action does not apply for that rule row.) Rule rows are read until there is a blank row. Multiple RuleTables can exist in a sheet.
- Row 20 contains another keyword, and a value. The row positions of keywords like this do not matter (most people put them at the top) but their column should be the same one where the RuleTable or RuleSet keywords should appear. In our case column C has been chosen to be significant, but any other column could be used instead.
Note
//row 18
rule "Cheese_fans_18"
when
Person(age=="42")
Cheese(type=="stilton")
then
list.add("Old man stilton");
end
Note
age=="42" and type=="stilton" are interpreted as single constraints, to be added to the respective ObjectType in the cell above. If the cells above were spanned, then there could be multiple constraints on one "column".
Warning
5.8. Data-Defining Cells
RuleSet, defines all DRL items except rules. The other one may occur repeatedly and is to the right and below a cell whose contents begin with RuleTable. These areas represent the actual decision tables, each area resulting in a set of rules of similar structure.
RuleSet cell and containing a keyword designating the kind of value contained in the other one that follows in the same row.
5.9. Rule Table Columns
RuleTable are earmarked as header area, mostly used for the definition of code to construct the rules. It is any additional row below these four header rows that spawns another rule, with its data providing for variations in the code defined in the Rule Table header.
Note
5.10. Rule Set Entries
RuleSet is upheld as the one containing the keyword.
5.11. Entries in the Rule Set Area
Table 5.1. Entries in the Rule Set area
| Keyword | Value | Usage |
|---|---|---|
| RuleSet | The package name for the generated DRL file. Optional, the default is rule_table. | Must be First entry. |
| Sequential | "true" or "false". If "true", then salience is used to ensure that rules fire from the top down. | Optional, at most once. If omitted, no firing order is imposed. |
| EscapeQuotes | "true" or "false". If "true", then quotation marks are escaped so that they appear literally in the DRL. | Optional, at most once. If omitted, quotation marks are escaped. |
| Import | A comma-separated list of Java classes to import. | Optional, may be used repeatedly. |
| Variables | Declarations of DRL globals, i.e., a type followed by a variable name. Multiple global definitions must be separated with a comma. | Optional, may be used repeatedly. |
| Functions | One or more function definitions, according to DRL syntax. | Optional, may be used repeatedly. |
| Queries | One or more query definitions, according to DRL syntax. | Optional, may be used repeatedly. |
| Declare | One or more declarative types, according to DRL syntax. | Optional, may be used repeatedly. |
5.12. Rule Attribute Entries in the Rule Set Area
Table 5.2. Rule Attribute Entries in the Rule Set Area
| Keyword | Initial | Value |
|---|---|---|
| PRIORITY | P | An integer defining the "salience" value for the rule. Overridden by the "Sequential" flag. |
| DURATION | D | A long integer value defining the "duration" value for the rule. |
| TIMER | T | A timer definition. See "Timers and Calendars". |
| CALENDARS | E | A calendars definition. See "Timers and Calendars". |
| NO-LOOP | U | A Boolean value. "true" inhibits looping of rules due to changes made by its consequence. |
| LOCK-ON-ACTIVE | L | A Boolean value. "true" inhibits additional activations of all rules with this flag set within the same ruleflow or agenda group. |
| AUTO-FOCUS | F | A Boolean value. "true" for a rule within an agenda group causes activations of the rule to automatically give the focus to the group. |
| ACTIVATION-GROUP | X | A string identifying an activation (or XOR) group. Only one rule within an activation group will fire, i.e., the first one to fire cancels any existing activations of other rules within the same group. |
| AGENDA-GROUP | G | A string identifying an agenda group, which has to be activated by giving it the "focus", which is one way of controlling the flow between groups of rules. |
| RULEFLOW-GROUP | R | A string identifying a rule-flow group. |
5.13. The RuleTable Cell
5.14. Column Types
5.15. Column Headers in the Rule Table
Table 5.3. Column Headers in the Rule Table
| Keyword | Initial | Value | Usage |
|---|---|---|---|
| NAME | N | Provides the name for the rule generated from that row. The default is constructed from the text following the RuleTable tag and the row number. | At most one column |
| DESCRIPTION | I | A text, resulting in a comment within the generated rule. | At most one column |
| CONDITION | C | Code snippet and interpolated values for constructing a constraint within a pattern in a condition. | At least one per rule table |
| ACTION | A | Code snippet and interpolated values for constructing an action for the consequence of the rule. | At least one per rule table |
| METADATA | @ | Code snippet and interpolated values for constructing a metadata entry for the rule. | Optional, any number of columns |
5.16. Conditional Elements
- Text in the first cell below CONDITION develops into a pattern for the rule condition, with the snippet in the next line becoming a constraint. If the cell is merged with one or more neighbours, a single pattern with multiple constraints is formed: all constraints are combined into a parenthesized list and appended to the text in this cell. The cell may be left blank, which means that the code snippet in the next row must result in a valid conditional element on its own.To include a pattern without constraints, you can write the pattern in front of the text for another pattern.The pattern may be written with or without an empty pair of parentheses. A "from" clause may be appended to the pattern.If the pattern ends with "eval", code snippets are supposed to produce boolean expressions for inclusion into a pair of parentheses after "eval".
- Text in the second cell below CONDITION is processed in two steps.
- The code snippet in this cell is modified by interpolating values from cells farther down in the column. If you want to create a constraint consisting of a comparison using "==" with the value from the cells below, the field selector alone is sufficient. Any other comparison operator must be specified as the last item within the snippet, and the value from the cells below is appended. For all other constraint forms, you must mark the position for including the contents of a cell with the symbol
$param. Multiple insertions are possible by using the symbols$1,$2, etc., and a comma-separated list of values in the cells below.A text according to the patternforall(delimiter){snippet}is expanded by repeating the snippet once for each of the values of the comma-separated list of values in each of the cells below, inserting the value in place of the symbol$and by joining these expansions by the given delimiter. Note that the forall construct may be surrounded by other text. - If the cell in the preceding row is not empty, the completed code snippet is added to the conditional element from that cell. A pair of parentheses is provided automatically, as well as a separating comma if multiple constraints are added to a pattern in a merged cell.If the cell above is empty, the interpolated result is used as is.
- Text in the third cell below CONDITION is for documentation only. It should be used to indicate the column's purpose to a human reader.
- From the fourth row on, non-blank entries provide data for interpolation as described above. A blank cell results in the omission of the conditional element or constraint for this rule.
5.17. Action Statements
- Text in the first cell below ACTION is optional. If present, it is interpreted as an object reference.
- Text in the second cell below ACTION is processed in two steps.
- The code snippet in this cell is modified by interpolating values from cells farther down in the column. For a singular insertion, mark the position for including the contents of a cell with the symbol
$param. Multiple insertions are possible by using the symbols$1,$2, etc., and a comma-separated list of values in the cells below.A method call without interpolation can be achieved by a text without any marker symbols. In this case, use any non-blank entry in a row below to include the statement.The forall construct is available here, too. - If the first cell is not empty, its text, followed by a period, the text in the second cell and a terminating semicolon are stringed together, resulting in a method call which is added as an action statement for the consequence.If the cell above is empty, the interpolated result is used as is.
- Text in the third cell below ACTION is for documentation only. It should be used to indicate the column's purpose to a human reader.
- From the fourth row on, non-blank entries provide data for interpolation as described above. A blank cell results in the omission of the action statement for this rule.
Note
$1 instead of $param will fail if the replacement text contains a comma.
5.18. Metadata Statements
- Text in the first cell below METADATA is ignored.
- Text in the second cell below METADATA is subject to interpolation, as described above, using values from the cells in the rule rows. The metadata marker character
@is prefixed automatically, and should not be included in the text for this cell. - Text in the third cell below METADATA is for documentation only. It should be used to indicate the column's purpose to a human reader.
- From the fourth row on, non-blank entries provide data for interpolation as described above. A blank cell results in the omission of the metadata annotation for this rule.
5.19. Interpolating Cell Data Example
- If the template is
Foo(bar == $param)and the cell is42, then the result isFoo(bar == 42). - If the template is
Foo(bar < $1, baz == $2)and the cell contains42,43, the result will beFoo(bar < 42, baz ==43). - The template
forall(&&){bar != $}with a cell containing42,43results inbar != 42 && bar != 43.
5.20. Tips for Working Within Cells
- Multiple package names within the same cell must be comma-separated.
- Pairs of type and variable names must be comma-separated.
- Functions must be written as they appear in a DRL file. This should appear in the same column as the "RuleSet" keyword. It can be above, between or below all the rule rows.
- You can use Import, Variables, Functions and Queries repeatedly instead of packing several definitions into a single cell.
- Trailing insertion markers can be omitted.
- You can provide the definition of a binding variable.
- Anything can be placed in the object type row. Apart from the definition of a binding variable, it could also be an additional pattern that is to be inserted literally.
- The cell below the ACTION header can be left blank. Using this style, anything can be placed in the consequence, not just a single method call. (The same technique is applicable within a CONDITION column.)
5.21. The SpreadsheetCompiler Class
SpreadsheetCompiler class is the main class used with API spreadsheet-based decision tables in the drools-decisiontables module. This class takes spreadsheets in various formats and generates rules in DRL.
SpreadsheetCompiler can be used to generate partial rule files and assemble them into a complete rule package after the fact. This allows the separation of technical and non-technical aspects of the rules if needed.
5.22. Using Spreadsheet-Based Decision Tables
Procedure 5.1. Task
- Generate a sample spreadsheet can to use as the base.
- If the Rule Workbench IDE plug-in is being used, use the wizard to generate a spreadsheet from a template.
- Use an XSL-compatible spreadsheet editor to modify the XSL.
5.23. Lists
lists of values. These can be stored in other worksheets to provide valid lists of values for cells.
5.24. Revision Control
5.25. Tabular Data Sources
5.26. Rule Template Capabilities
- store your data in a database (or any other format)
- conditionally generate rules based on the values in the data
- use data for any part of your rules (e.g. condition operator, class name, property name)
- run different templates over the same data
5.27. Rule Template Example
1 template header
2 age
3 type
4 log
5
6 package org.drools.examples.templates;
7
8 global java.util.List list;
9
10 template "employees"
11
12 rule "Current employee_@{row.rowNumber}"
13 when
14 Name(location == @{location})
15 role(type == "@{type}")
16 then
17 list.add("@{log}");
18 end
19
20 end template
- Line 1: All rule templates start with
template header. - Lines 2-4: Following the header is the list of columns in the order they appear in the data. In this case we are calling the first column
location, the secondtypeand the thirdlog. - Line 5: An empty line signifies the end of the column definitions.
- Lines 6-9: Standard rule header text. This is standard rule DRL and will appear at the top of the generated DRL. Put the package statement and any imports and global and function definitions into this section.
- Line 10: The keyword
templatesignals the start of a rule template. There can be more than one template in a template file, but each template should have a unique name. - Lines 11-18: The rule template.
- Line 20: The keywords
end templatesignify the end of the template.
package org.drools.examples.templates;
global java.util.List list;
rule "Current employee_1"
when
Person(location == Melbourne)
role(type == "receptionist")
then
list.add("melbourne admin");
end
rule "Current employee_2"
when
Person(location == Sydney)
Cheese(type == "recruiter")
then
list.add("sydney HR");
end
5.28. Executing Rule Templates
Procedure 5.2. Task
- Run this code to execute your rule template:
DecisionTableConfiguration dtableconfiguration = KnowledgeBuilderFactory.newDecisionTableConfiguration(); dtableconfiguration.setInputType( DecisionTableInputType.XLS ); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newClassPathResource( getSpreadsheetName(), getClass() ), ResourceType.DTABLE, dtableconfiguration );
5.29. Extended Changeset Example
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >
<add>
<resource source='http:org/domain/myrules.drl' type='DRL' />
<resource source='classpath:data/IntegrationExampleTest.xls' type="DTABLE">
<decisiontable-conf input-type="XLS" worksheet-name="Tables_2" />
</resource>
</add>
</change-set>
5.30. Changesets and Directories Example
<change-set xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set.xsd http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >
<add>
<resource source='file://myfolder/' type='DRL' />
</add>
</change-set>
5.31. Knowledge Agent
5.32. Knowledge Agent Example
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "MyAgent" ); kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) ); KnowledgeBase kbase = kagent.getKnowledgeBase();
5.33. KnowledgeAgent Objects
KnowledgeAgent object will continuously scan all resources using a default polling interval of 60 seconds. When a modification date is updated, it will applied the changes into the cached Knowledge Base using the new resources. The previous KnowledgeBase reference will still exist and you'll have to call getKnowledgeBase() to access the newly built KnowledgeBase. If a directory is specified as part of the change set, the entire contents of that directory will be scanned for changes. The way modifications are applied depends on drools.agent.newInstance property present in the KnowledgeAgentConfiguration object passed to the agent.
5.34. Starting Polling Services
Procedure 5.3. Task
- For polling to occur, the polling and notifier services must be started. Use this code:
ResourceFactory.getResourceChangeNotifierService().start(); ResourceFactory.getResourceChangeScannerService().start();
5.35. Custom ClassLoaders for KnowledgeBuilder
Procedure 5.4. Task
- Open a KnowledgeBuilderConfiguration and specify a custom classloader.
- If you need to pass custom configuration to these compilers, sends a KnowledgeBuilderConfiguration object to KnowledgeAgentFactory.newKnowledgeAgent().
5.36. Reusing the KnowledgeBase ClassLoader
drools.agent.useKBaseClassLoaderForCompiling property of KnowledgeAgentConfiguration object.
5.37. KnowledgeAgentConfiguration Example
KnowledgeBaseConfiguration kbaseConfig =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, customClassLoader);
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(kbaseConfig); //kbase with custom classloader
KnowledgeAgentConfiguration aconf =
KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty("drools.agent.newInstance", "false"); //incremental change set processing enabled
aconf.setProperty("drools.agent.useKBaseClassLoaderForCompiling", "true");
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
"test agent", kbase, aconf);5.38. The newInstance Property
5.39. Using the newInstance Property
5.40. newInstance Example
KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty("drools.agent.newInstance", "false");
KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent("test agent", null, aconf);
5.41. Remote HTTP Resource Caching
5.42. Restoring Resource Caching After a Restart
Procedure 5.5. Task
- To survive a restart when a resource is no longer available remotely (for example, the remote server is being restarted), set a System Property:
drools.resource.urlcache. (Make sure it is set to a directory that has write permissions for the application.) The Knowledge Agent will cache copies of the remote resources in that directory.For example, using the java command line-Ddrools.resource.urlcache=/users/someone/KnowledgeCache- will keep local copies of the resources (rules, packages etc) in that directory, for the agent to use should it be restarted. (When a remote resource becomes available, and is updated, it will automatically update the local cache copy.)

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.