Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

As a Java developer, you can make life a lot easier by using Drools to implement business rules. This book shows you how with clear instructions across the whole range of efficiencies the platform provides.

Domain Specific Language

The domain in this sense represents the business area (for example, life insurance or billing). Rules are expressed with the terminology of the problem domain. This means that domain experts can understand, validate, and modify these rules more easily.

You can think of DSL as a translator. It defines how to translate sentences from the problem-specific terminology into rules. The translation process is defined in a .dsl file. The sentences themselves are stored in a .dslr file. The result of this process must be a valid .drl file.

Building a simple DSL might look like:

[condition][]There is a Customer with firstName 
{name}=$customer : Customer(firstName == {name})
[consequence][]Greet Customer=System.out.println("Hello " +

Code listing 1: Simple DSL file, simple.dsl.

The code listing above contains only two lines (each begins with [). However, because the lines are too long, they are wrapped effectively creating four lines. This will be the case in most of the code listings.
When you are using the Drools Eclipse plugin to write this DSL, enter the text before the first equal sign into the field called Language expression, the text after equal sign into Rule mapping, leave the object field blank, and select the correct scope.

The previous DSL defines two DSL mappings. They map a DSLR sentence to a DRL rule. The first one translates to a condition that matches a Customer object with the specified first name. The first name is captured into a variable called name. This variable is then used in the rule condition. The second line translates to a greeting message that is printed on the console. The following .dslr file can be written based on the previous DSL:

package droolsbook.dsl;
expander simple.dsl
rule "hello rule"
There is a Customer with firstName "David"
Greet Customer

Code listing 2: Simple .dslr file (simple.dslr) with rule that greets a customer with name David.

As can be seen, the structure of a .dslr file is the same as the structure of a .drl file. Only the rule conditions and consequences are different. Another thing to note is the line containing expander simple.dsl. It informs Drools how to translate sentences in this file into valid rules. Drools reads the simple.dslr file and tries to translate/expand each line by applying all mappings from the simple.dsl file (it does it in a single pass process, line-by-line from top to bottom). The order of lines is important in a .dsl file. Please note that one condition/consequence must be written on one line, otherwise the expansion won't work (for example, the condition after the when clause, from the rule above, must be on one line).

When you are writing .dslr files, consider using the Drools Eclipse plugin. It provides a special editor for .dslr files that has an editing mode and a read-only mode for viewing the resulting .drl file. A simple DSL editor is provided as well.

The result of the translation process will look like the following screenshot:

Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

This translation process happens in memory and no .drl file is physically stored. We can now run this example. First of all, a knowledge base must be created from the simple.dsl and simple.dslr files. The process of creating a package using a DSL is as follows (only the package creation is shown)

Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

KnowledgeBuilder acts as the translator. It takes the .dslr file, and based on the .dsl file, creates the DRL. This DRL is then used as normal (we don't see it; it's internal to KnowledgeBuilder). The implementation is as follows:

private KnowledgeBase createKnowledgeBaseFromDSL()
throws Exception {
KnowledgeBuilder builder =
"simple.dsl"), ResourceType.DSL);
"simple.dslr"), ResourceType.DSLR);
if (builder.hasErrors()) {
throw new RuntimeException(builder.getErrors()

KnowledgeBase knowledgeBase = KnowledgeBaseFactory
return knowledgeBase;

Code listing 3: Creating knowledge base from .dsl and .dslr files.

The .dsl and subsequently the .dslr files are passed into KnowledgeBuilder. The rest is similar to what we've seen before.

DSL as an interface

DSLs can be also looked at as another level of indirection between your .drl files and business requirements. It works as shown in the following figure:

Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

The figure above shows DSL as an interface (dependency diagram). At the top are the business requirements as defined by the business analyst. These requirements are represented as DSL sentences (.dslr file). The DSL then represents the interface between DSL sentences and rule implementation (.drl file) and the domain model. For example, we can change the transformation to make the resulting rules more efficient without changing the language. Further, we can change the language, for example, to make it more user friendly, without changing the rules. All of this can be done just by changing the .dsl file.

DSL for validation rules

We'll rewrite the three usually implemented object/field required rules as follows:

  • If the Customer does not have an address, then Display warning message
  • If the Customer does not have a phone number or it is blank, then Display error message
  • If the Account does not have an owner, then Display error message for Account

We can clearly see that all of them operate on some object (Customer/Account), test its property (address/phone/owner), and display a message (warning/error) possibly with some context (account). Our validation.dslr file might look like the following code:

expander validation.dsl

rule "address is required"
The Customer does not have address
Display warning

rule "phone number is required"
The Customer does not have phone number or it is blank
Display error

rule "account owner is required"
The Account does not have owner
Display error for Account

Code listing 4: First DSL approach at defining the required object/field rules (validation.dslr file).

The conditions could be mapped like this:

[condition][]The {object} does not have {field}=${object} : {object}( 
{field} == null )

Code listing 5: validation.dsl.

This covers the address and account conditions completely. For the phone number rule, we have to add the following mapping at the beginning of the validation.dsl file:

[condition][] or it is blank = == "" ||

Code listing 6: Mapping that checks for a blank phone number.

As it stands, the phone number condition will be expanded to:

$Customer : Customer( phone number == "" || == null )

Code listing 7: Unfinished phone number condition.

To correct it, phone number has to be mapped to phoneNumber. This can be done by adding the following at the end of the validation.dsl file:

[condition][]phone number=phoneNumber

Code listing 8: Phone number mapping.

The conditions are working. Now, let's focus on the consequences. The following mapping will do the job:

[consequence][]Display {message_type} for {object}={message_type}( 
kcontext, ${object} );
[consequence][]Display {message_type}={message_type}( kcontext );

Code listing 9: Consequence mappings.

The three validation rules are now being expanded to the .drl representation

File formats

Before we go further, we'll examine each file format in more detail.

DSL file format

A line in a .dsl file has the following format:

[<scope>][<Type>]<language expression>=<rule mapping>

Code listing 10: The format of one line in a .dsl file.

As we've already seen, an example of a line in DSL file might look like this:

[condition][]The Customer does not have
address=Customer(address == null)

Code listing 11: Sample line from DSL file (note that it is just one line that has been wrapped).

The scope can have the following values:

  • condition: Specifies that this mapping can be used in the condition part of a rule.
  • consequence: Specifies that this mapping can be used in the consequence part of a rule.
  • *: Specifies that this mapping can be used in both the condition and the consequence part of a rule.
  • keyword: This mapping is applied to the whole file (not just the condition or the consequence part). Used mainly when writing DSLs in languages other than English or to hide the package/import/global statements at the beginning of the file behind a business friendly sentence.

Type can be used to further limit the scope of the mapping. Scope and Type are used by the Drools Eclipse plugin to provide auto-completion when writing .dslr files (when pressing Ctrl + Space, only relevant choices are offered). This is especially useful with the multiple constraints feature (refer to the section, DSL for multiple constraints in a condition).

DSL supports comments by starting the line with the hash character, #. For example:

#this is a comment in a .dsl file

DRL file format

As a side note, in a .drl file, it is valid to write the whole rule on a single line. This allows us to write more complex DSLs because one sentence in .dslr file can be translated into multiple conditions—even the whole rule. For example, these are valid rules on a single line:

rule "addressRequired" when Customer( address == null ) then 
warning(kcontext); end

Code listing 12: addressRequired rule on one line.

Make sure that you add spaces between Drools keywords. Another more complex example of a rule on one line:

rule "studentAccountCustomerAgeLessThan" when Customer( eval (
yearsPassedSince(dateOfBirth) >= 27) ) and $account : Account( type ==
Account.Type.STUDENT ) then error(kcontext, $account);
System.out.println("another statement"); end

Code listing 13: studentAccountCustomerAgeLessThan rule on one line.

The preceding rule contains two conditions and two Java statements in the consequence block. There is also an optional and keyword between the conditions to make it more readable.

DSLR file format

A .dslr file contains the sentences written using the DSL. The .dslr file is very similar to the .drl file.  One thing to note is that by prepending a line with a '>', we can turn off the expander for the line. This allows us to write a hybrid .dslr file that contains traditional DRL rules and DSL rules. For example, if we are not yet sure how to map some complex rule, we can leave it in its original .drl file format.

DSL for multiple constraints in a condition

We'll go through more complex DSLs. Let's look at a standard condition for example:

Account( owner != null, balance > 100, currency == "EUR" )

Code listing 14: Condition that matches some account.

It is difficult to write DSL that will allow us to create conditions with any subset of constraints from the code listing above (without writing down all possible permutations). The '-' feature comes to the rescue:

[condition][]There is an Account that=$account : Account( )
[condition][]-has owner=owner != null
[condition][]-has balance greater than {amount}=balance > {amount}
[condition][]-has currency equal to {currency}=currency == {currency}

Code listing 15: DSL using the '-' feature. This can create seven combinations of the constraints.

When the DSL condition starts with '-', the DSL parser knows that this constraint should be added to the last condition (in a .dslr file). With the preceding DSL, the following condition can be created:

There is an Account that
- has currency equal to "USD"
"has balance greater than 2000"

Code listing 16: Condition using the '-' feature (in a .dslr file).

The '-' feature increases the flexibility of the resulting language. It works just fine for simple cases involving only one pair of brackets. In case of multiple brackets in the condition, Drools always adds the constraint to the last pair of brackets. This may not always be what we want. We have to find a different way of specifying multiple constraints in a condition. We can also write our DSL in the following manner:

[condition][]There is an Account that {constraints} = Account( 
{constraints} )
[condition][]has {field} equal to {value}={field} == {value}
[condition][]and has {field} equal to {value}=, {field} == {value}

Code listing 17: Flexible DSL that can be expanded to a condition with two field constraints.

With this DSL, the following DSLR can be written:

There is an Account that has owner equal to null and has balance equal to 100

Code listing 18: DSLR that describes an account with two constraints.

If we want to have more conditions, we can simply duplicate the last line in the DSL. Remember? Translation is a single pass process.

Named capture groups

Sometimes, when a more complex DSL is needed, we need to be more precise at specifying what a valid match is. We can use named capture groups with regular expressions to give us the needed precision. For example:


Code listing 19: Name that matches only characters.

Regular expressions (java.util.regex.Pattern) can be used not only for capturing variables but also within the DSL. For example, in order to carry out case insensitive matching. If we look at the DSL from code listing 15, the users should be allowed to type Account, account, ACCOUNT, or even aCcount in their .dslr files. This can be done by enabling the embedded case insensitive flag expression—(?i):
[condition][]There is an (?i:account) that ....
Another useful example is sentences that are sensitive to gender—(s)?he to support "he" and "she", and so on. In order to make the sentences space insensitive, Drools automatically replaces all spaces with s+. Each s+ matches one or more spaces. For example, the following line in a .dslr file will be successfully expanded by the DSL from code listing 15:
There is an Account that ....

DSL for data transformation rules

We'll now implement DSL for the data transformation rules. We'll reuse our rule unit tests to verify that we don't change the functionality of the rules but only their representation. The unit test class will be extended and the method for creating KnowledgeBase will be overridden to use the .dsl file and .dslr file as inputs. Rule names will stay the same. Let's start with the twoEqualAddressesDifferentInstance rule:

rule twoEqualAddressesDifferentInstance 
There is legacy Address-1
There is legacy Address-2
- same as legacy Address-1
remove legacy Address-2
Display WARNING for legacy Address-2

Code listing 20: Rule for removing redundant addresses (dataTransformation.dslr file).

The conditions can be implemented with the following DSL:

[condition][] legacy {object}-{id} = {object}-{id}
[condition][] There is {object}-{id} = ${object}{id} : Map(
this["_type_"] == "{object}" )
[condition][]- same as {object}-{id} = this == ${object}{id}, eval(
${object}1 != ${object}2 )

Code listing 21: DSL for conditions (dataTransformation.dsl file).

The first mapping is a simple translation rule, where we remove the word legacy. The next mapping captures a map with its type. The last mapping includes the equality test with the object identity test. Mapping for consequences is as follows:

[consequence][] legacy {object}-{id} = ${object}{id}
[consequence][]Display {message_type_enum} for {object}=validationRepo
enum}, kcontext.getRule().getName(), {object}));
[consequence][]remove {object} = retract( {object} );

Code listing 22: DSL for consequences.

The first mapping just removes the word legacy. The second mapping adds a message to validationReport. Finally, the last mapping removes an object from the knowledge session. This is all we need for the twoEqualAddressesDifferentInstance rule.

As you can see, we started with the sentence in the domain specific language (code listing 1) and then we've written the transformation to reflect the rules. In reality, this is an iterative process. You'll modify the .dslr and .dsl files until you are happy with the results. It is also a good idea to write your rules in standard .drl first and only then try to write a DSL for them.

We'll move to the next rule, addressNormalizationUSA:

rule addressNormalizationUSA
There is legacy Address-1
- country is one of "US", "U.S.", "USA", "U.S.A"
for legacy Address-1 set country to USA

Code listing 23: DSLR rule for normalizing address country field.

The rule just needs another constraint type:

[condition][]- country is one of {country_list} = this["country"] in 

Code listing 24: Another condition mapping.

The consequence is defined with two mappings. The first one will translate the country to an enum and the second will then perform the assignment.

[consequence][]set country to {country}=set country to Address.
[consequence][]for {object}set {field} to {value} = modify( {object} )
{ put("{field}", {value} ) }

Code listing 25: Consequence mapping for the country normalization rule.

Please note that the curly brackets are escaped. Moreover, the original rule used mvel dialect. It is a good idea to write your rules using the same dialect. It makes the DSL easier. Otherwise, the DSL will have to be "dialect aware".

The other country normalization rule can be written without modifying the DSL. We'll now continue with unknownCountry rule:

rule unknownCountry
Apply after address normalizations
There is legacy Address-1
- country is not normalized
Display ERROR for legacy Address-1

Code listing 26: DSLR representation of the unknownCountry rule.

The whole sentence, Apply after address normalizations is mapped as a keyword mapping:

[keyword][] Apply after address normalizations = salience -10

Code listing 27: salience keyword mapping.

Now, we can use the other rule attributes to achieve the same goal just by changing the DSL.

Additional mapping that is needed:

[condition][]- country is not normalized = eval(!($Address1.
get("country") instanceof Address.Country))

Code listing 28: Another condition mapping.

In the condition mapping, $Address1 is hard-coded. This is fine for the rules that we have.

As you can imagine, the rest of the rules follow similar principles.

What we have achieved by writing this DSL is better readability. A business analyst can verify the correctness of these rules more easily. We could push this further by defining a complete DSL that can represent any concept from the problem domain. The business analyst will then be able to express any business requirement just by editing the .dslr file.


Decision tables

Decision tables are another form of human-readable rules that are useful when there are lots of similar rules with different values. Rules that share the same conditions with different parameters can be captured in a decision table. Decision tables can be represented in an Excel spreadsheet (.xls file) or in comma separated values (.csv         file) format. Starting from version 5.0, Drools supports web-based decision tables as well. They are very similar. Let's have a look at a simple decision table in .xls format.

Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

The preceding screenshot shows a decision table in validation.xls opened with OpenOffice Calc editor. It shows one decision table for validating a customer. Line 10 shows four columns. The first one defines rule name, the next two define conditions, and the last one is for defining actions/consequences. The next three lines (11-13) represent the individual rules—one line per rule. Each cell defines parameters for conditions/consequences. If a cell doesn't have a value, that condition/action is ignored. Some rows in the spreadsheet are grouped and hidden (see the two plus (+) signs in the left). This makes the decision tables more user-friendly, especially for business users. Please note that tables don't have to start on the first column. The full validation.xls file is as follows:

Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

Every file for defining decision tables start with a global configuration section. The configuration consists of name-value pairs. As can be seen from the screenshot above:

  • RuleSet defines the package
  • Import specifies the classes used, including static imported functions
  • Variables is used for global variables
  • Notes can be any text


  • Functions can be used to write local functions as in .drl format
  • Worksheet specifies the sheet to be used; by default only the first sheet is checked for rules

The RuleTable then denotes the start of the decision table. It has no specific purpose. It is used only to group rules that operate on the same objects and share conditions. The next line defines column types. The following column types are available:

  • CONDITION—defines a single rule condition or constraint, the following row can contain type for this condition, if it doesn't, then the next row must define full condition (with a type, not just a constraint as in the preceding case).
  • ACTION—rule action. Similar to condition, the next line can contain any global or bound variable. Drools will then assume that the next line is a method that should be called on this global or bound variable.
  • PRIORITY—for defining rule salience.
  • NAME—by default rule names are auto generated, NAME can be used to explicitly specify the name.
  • No-loop or Unloop—specifies the rule no-loop attribute.
  • XOR-GROUP—specifies rule activation-group (this will be discussed in the second part of this article in the section, Drools Flow).

For full configuration options, please consult the Drools manual (

The next line from the preceding screenshot looks similar to what we see in a .drl file. It is a simple condition that matches any Customer object and exposes this object as the $customer variable. The only difference is that there are no brackets. They will be added automatically by Drools at parsing time. Please note that this line contains only two columns. The first two columns are merged into one column. This is because they operate on the same type (Customer). If we don't merge the two columns, they'll match two separate objects (which may or may not be the same instance).

The next line then defines individual constraints (in case of conditions) or code blocks (in case of actions). Special parameters can be used as $param or $1, $2, $3, and so on. The first one is used if our constraint needs only one parameter; otherwise, the $n format should be used.

The following line (corresponds to line 10 in the preceding screenshot showing a decision table in validation.xls file) is for pure informational purposes. It should contain some meaningful description of the column/action so that we don't have to always look at how it is implemented (by expanding/collapsing rows).

Finally, the actual values follow in subsequent rows. Each line represents one rule. For example, the first line gets translated behind the scenes to the following .drl rule:

#From row number: 11
rule "addressRequired"
$customer : Customer(address == null)

Code listing 29: Generated rule from a decision table.

Advantages of a decision table

Here are the advantages of a decision table:

  • It is easy to read and understand.
  • Refactoring is quicker because we just have to change a column definition to change a group of related rules (that is, it is easy to change conditions across group of rules).
  • Isolation is similar to DSL; decision tables can hide the rule implementation details.
  • Provides separation between the rules and data (they are still in one file but separated).
  • Any formatting available in a spreadsheet editor can be applied to present these data in a more readable manner (for example, using a drop-down for a list of values. It can reduce errors from mistyping a value into a cell by allowing only valid values).        
  • Eclipse Drools plugin can also validate a spreadsheet. This is very useful when writing rules. The Problems view in Eclipse shows what exactly is wrong with the generated .drl file.

Disadvantages of a decision table

  • It can be awkward to debug/write these rules. Sometimes it helps to convert the spreadsheet to a .drl file, save this file, and fix it, as we're used to.
  • Decision tables shouldn't be used if the rules don't share many conditions. Further, the order of conditions is important. In a decision table, the order of a condition is given by the order of a column. Care should be taken if you want to convert the existing DRL rules into decision tables, as the order of conditions may change (to take advantage of the reuse).
  • XLS is a binary format which makes version management more difficult.

Calculating the interest rate

As an example, we'll calculate the interest rate based on the account balance, currency, duration, and type. This calculation is ideal for a decision table because we have a lot of constraints that are reused across rules with different data. The decision table looks as follows:

Human-readable Rules with Drools JBoss Rules 5.0(Part 1)

Please note that the Account object is used in every condition so the CONDITION columns are merged. We can see the use of parameters $1 and $2. The first line can be read as: For every transactional account with currency EUR, set its interest rate to 0.01 percent (regardless of the balance). Another line can be read as: For every savings account whose balance is between 100 EUR and 1000 EUR that is opened for one to three months, set its interest rate to 3 percent. The following rule will be generated:

#From row number: 16
rule "Interest Calculation_16"
$a:Account(type == Account.Type.SAVINGS,
currency == "EUR", balance >= 100 && < 1000,
monthsBetweenStartAndEndDate >= 1 && < 3)
$a.setInterestRate(new BigDecimal("3.00"));

Code listing 30: Generated rule for calculating the interest rate.

If we had not used a decision table, we would have to write such rules by hand. Please note that the second condition column in the decision table above doesn't have any operator or operand. It simply says currency. It is a special feature and this is automatically translated to currency == $param.

The last condition column uses getMonthsBetweenStartAndEndDate method of the Account class.

 private DateMidnight startDate;
private DateMidnight endDate;

* @return number of months between start and end date
public int getMonthsBetweenStartAndEndDate() {
if (startDate == null || endDate == null) {
return 0;
return Months.monthsBetween(startDate, endDate)

Code listing 31: Implementation of getMonthsBetweenStartAndEndDate method of Account.

The implementation uses the Joda-Time library to do the calculation.

Project setup

The following libraries are needed on the classpath:

  • drools-decisiontables-5.0.1.jar: used for compiling spreadsheets into .drl file format; it knows how to handle .xls and .csv formats.
  • jxl-2.4.2.jar XLS API: used for parsing .xls spreadsheets.


For testing the interest calculation rules, we'll use a stateless knowledge session, an account, and a date object. All tests will reuse the stateless session. The test can be set up as follows:

  static StatelessKnowledgeSession session;
Account account;
static DateMidnight DATE;

public static void setUpClass() throws Exception {
KnowledgeBase knowledgeBase =
session = knowledgeBase.newStatelessKnowledgeSession();
DATE = new DateMidnight(2008, 1, 1);

public void setUp() throws Exception {
account = new Account();

Code listing 32: Setup of the decision table test. The date will be used to set deposit durations. An account is created for every test method. The createKnowledgeBaseFromSpreadsheet method is implemented as follows:

private static KnowledgeBase createKnowledgeBaseFromSpreadsheet()
throws Exception {
DecisionTableConfiguration dtconf =KnowledgeBuilderFactory
dtconf.setInputType( DecisionTableInputType.XLS );
//dtconf.setInputType( DecisionTableInputType.CSV );

KnowledgeBuilder knowledgeBuilder =
"interest calculation.xls"), ResourceType.DTABLE,
// .newClassPathResource("interest calculation.csv"),
// ResourceType.DTABLE, dtconf);

if (knowledgeBuilder.hasErrors()) {
throw new RuntimeException(knowledgeBuilder.getErrors()

KnowledgeBase knowledgeBase = KnowledgeBaseFactory
return knowledgeBase;

Code listing 33: Creating a knowledgeBase from a spreadsheet.

As opposed to the other knowledge definitions, the decision table needs a special configuration that is encapsulated in DecisionTableConfiguration class. This configuration specifies the type of decision table and it is then passed on to the knowledge builder. The commented lines show how to create a knowledge base from a .csv format. The rest should be familiar.

Note, if you want to see the generated .drl source, you can get it like this:

String drlString = DecisionTableFactory
.newClassPathResource("interest calculation.xls")
.getInputStream(), dtconf);

Code listing 34: Getting the .drl representation of the decision table. It is stored in a drlString string variable; it can be printed to the console and used for debugging purposes.

We'll now write a test for depositing 125 EUR for 40 days:

public void deposit125EURfor40Days() throws Exception {
account.setBalance(new BigDecimal("125.00"));


assertEquals(new BigDecimal("3.00"), account

Code listing 35: Test for depositing 125 EUR for 40 days. The preceding test verifies that the correct interest rate is set on the account.

And one test for default transactional account rate:

public void defaultTransactionalRate() throws Exception {


assertEquals(new BigDecimal("0.01"), account

Code listing 36: Test for the default transactional account rate.

The test above, again, verifies that the correct interest rate is set.

Comma Separated values

The XLS spreadsheet can be easily converted into CSV format. Just select Save as CSV in your spreadsheet editor. However, there is one caveat—CSV format doesn't support merging of columns by default. For overcoming this, Drools has the following workaround: if we add three dots at the end of type declarations, they will be merged into one. It can be seen in the last line of the following CSV excerpt:

"RuleTable Interest Calculation",,,,

Code listing 37: Excerpt from the interest calculation.csv file.

It is the only change that needs to be done. Tests should pass for CSV format as well.

CSV is a text format as opposed to XLS, which is a binary format. Binary format makes version management harder. For example, it is very difficult to merge changes between two binary files. CSV doesn't have these problems. On the other hand, the presentation suffers.

Rule Templates

If you like the concept of decision tables, you may want to look at Drools Rule Templates. They are similar to the decision tables but more powerful. With Rule Templates, the data is fully separated from the rule (for example, it can come from a database and have different templates over the same data). You have more power in defining the resulting rule. The data can define any part of rule (for example, condition operator, class, or property name). For more information, refer to the Rule Templates section of the Drools Experts User Guide (available at


In this article, we've learned about writing more user-friendly rules using DSLs, and decision tables. You can mix and match these approaches. It makes sense to write some rules using DSL, some using decision tables, and more complex rules using pure .drl file format. KnowledgeBase can be created from multiple sources.

DSLs are very useful if there is a need for the business analyst to read and understand the existing rules and even write new rules. The resulting language uses businesses terminologies making it more natural for the business analyst. DSL provides an abstraction layer that hides complicated rule implementations. The Eclipse editor brings auto competition so that the rules are easier to write.

Decision tables, on the other hand, are useful when we have a lot of similar rules that use different values as was the case in the interest rate calculation example. It makes it easy to change such rules because the rule implementation is decoupled from the values they use. Spreadsheet format is also more concise. We can fit more rules into one screen, which makes it easier to understand the overall picture.

In the next part, we'll learn about Drools Flow, ruleflow, and other aspects.

If you have read this article you may be interested to view :

Books to Consider

comments powered by Disqus

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free