How to Write a Drools Business Rule

Posted by Jared Grabill in how-to drools

In Part 1 of our Drools tutorial series, we take a look at the anatomy of a business rule in the Drools rule engine.

What is a business rule?

A rule is a single logic statement comprised of a “when” clause (the condition) and a “then” clause (the consequences when the condition is met). A business rule applies this concept to representing concepts in business, for example when to apply a discount or approve a credit application.

Rules engines allow for executing many rules in tandem to achieve complex logic while keeping individual rules concise and easy to understand.

Now, let’s take a look at what makes up a rule.

Anatomy of a rule

A Rule consists of a condition that triggers it (when) and a consequence that performs actions (then) when it is fired.

Regardless of whether you are hand writing a Drools rule or using a guided designer, rules will always have the below structure:

Anatomy of a Drools Rule

  • Rule header - The rule header declares the name of the rule, and must be unique.
  • Attributes - This region may contain optional attributes of the rule to modify the execution behavior, grouping, and add additional information.
  • Conditions - This region contains zero or more patterns which will match against the facts in memory. If matching facts are found, the actions are performed.
  • Consequences - This region specifies the actions to be performed if the rule’s condition is met.

Conditions (when)

The “when” part of a rule (also known as the Left Hand Side, or LHS, of the rule) contains the conditions that must be met to execute an action. Conditions consist of a series of stated patterns and constraints based on the available data objects.

Example: If a bank requires loan applicants to be over 21 years of age, then the when condition of an "Underage" rule would be Driver(age < 21).

Patterns match on “Facts”, where are the objects in current working memory of Drools. An example might be a Driver fact with age and height properties. Facts are added into the rules engine knowledge set before execution, and may also be created and modified by rules as they execute.

Consequences (then)

The “then” part of the rule (also known as the Right Hand Side, or RHS, of the rule) contains the actions to be performed when the conditional part of the rule has been met.

Example: If a bank requires loan applicants to be over 21 years of age (with a rule condition Driver(age < 21)) and a loan applicant is under 21 years old, then the action of an "Underage" rule would be setApproved(false), declining the loan because the applicant is under age.

The main purpose of consequences (rule actions) are to insert, delete, or modify data (also known as “facts”) throughout the execution process.

Effective rule actions are small, declarative, and readable. If you need to use imperative or conditional code in rule actions, then divide the rule into multiple smaller and more declarative rules.

Actions consist of one or more methods that execute consequences based on the rule conditions and on available data objects.

Next, we will take a look at how to write a rule.


Writing the condition (the When)

To define the conditions for a Drools rule to fire, a special pattern syntax is used:

  when
    Driver( age < 21 )
  then
    ...

Here the condition can contain patterns (Driver(...)) which will match facts with the same name. Internally the pattern can contain additional constraints, in this case specifying that age be less than 21 to match. If a matching pattern is found, the action(s) in the “then” section of the rule will be executed. If no matches are found, no action is taken.

Can we have a rule with an empty condition and no patterns? Absolutely. In this case the rule actions always fire, which can be handy for initializing data:

  when    
    // no conditions
  then
    ...

To declare a more specific condition on our Driver fact, say matching a property gender to “male”, we can separate then with commas:

  when
    Driver( age < 21, gender == "male" )
  then
    ...

To match on multiple facts, say the presence of an additional Vehicle fact, we can add each to a new line in the when:

  when
    Driver( age < 21, gender == "male" )
    Vehicle()
  then
    ...

Note the lack of constraints in the Vehicle fact condition- this instructs the engine to match the rule if any Vehicle exists. Using this simple syntax, each consequence can be thought as having a logical AND.

To match a condition that does not exist, we can use the not keyword:

  when
    not Vehicle()
  then
    ...

This rule will fire if there are no Vehicle facts inserted into working memory.

Variables

To capture data from a fact, or the entire fact, for use in the rule actions will we need to create variables. The common convention is to name each variable starting with a ‘$’.

To capture an entire fact as a variable, for example our Driver fact, prefix it with the name of the variable and a colon:

  $d : Driver( age < 21, gender == "male" )

If we only need the age, the same convention applies:

  Driver( $age : age < 21, gender == "male" )

Generally, capturing only the specific data needed is preferred.


Writing the consequence (the Then)

At this point, we are able to construct a rule that can fire when certain conditions are met. Now, lets look at how to perform some actions.

Inserting and Modifying Facts

Drools provides specific statements that are used to modify, update, insert, or delete facts during rule execution.

The action methods we will focus on for this example are:

  • set - Modifies a property of a fact, but does not notify the engine
  • update Notifies the engine that a fact was changed from one or more sets
  • modify Groups several property set modifications and notifies the engine in one operation
  • insert Inserts a new fact

Lets look at how to insert an Approval fact if a Driver is 21 or older.

  when
    Driver( age >= 21 )
  then
    insert( new Approval() )

Note that the syntax of the “Then” area is normal Java. If we wanted to set an additional property on our Approval object, we could do it like this:

  when
    Driver( age >= 21 )
  then
    Approval app = new Approval();
    app.setDate = new Date();
    insert( app )

Now to look at modifying a fact. If we would like to add 1 to a property risk on a Driver if under 21, we could use our captured variable like this:

  when
    $d : Driver( age >= 21, $risk : risk )
  then
    $d.setRisk = $risk + 1;
    update( $d )

Note the required update action which tells the Drools engine that this fact was updated.

It is important to note that when you change a fact in the consequence (using *set* or any mutating property) that change updates the fact but does not make the changed data available to other rules. In turn, changes to fact using this approach are not "reactive" and other rules will not be aware of the change unless *update* is called or *modify* is used. Inserted facts, on the other hand, are immediately available to other rules without calling *update*.

We could, alternatively, use the modify action which will automatically perform this update for us:

  when
    $d : Driver( age >= 21, $risk : risk )
  then
    modify( $d ) {
      setRisk = $risk + 1;
    }

Using these combinations of patterns and actions, we can begin to achieve some more powerful logic. For example, a second rule could use a pattern that matches when the risk for a Driver is greater than 2, then insert a Denied fact. We will look at deeper examples of interacting rules like this in Part 2 of this series.


Conclusion

This has been just a small taste of the power of Drools using some simple examples. Be sure to subscribe to get notified of future guides like this, and of course check out our Sparks Platform which can get you up and running with production Drools in minutes.

For more detailed explanations of the rules and their syntax refer to these links:

how-to drools

Subscribe to the Logicdrop Newsletter

Join hundreds of fellow users for tips, deeps dives, and best practices for implementing business rules and automation.

Try the Logicdrop Platform risk-free for 30 days.

No credit card required. Have questions? Contact us.

closing x