EZ-Rules Documentation

ez-rules

Introduction

During my career in been involved in many project where the use of a business rules engine will be the perfect match, however most of the times the size of the project the constrains (time, money, etc) was decided not to use some of the well know and well positioned Rule framework like Drools, JRules, etc. In many of those projects we end creating a lightweight rule engine in order to solve the solution

The main inspiration of this project was to create a simple to use, light, standalone Java Rule Engine that can be use as simple as possible in any project where a rule engine design is necessary.

Looking for a good definition  for a Rule Engine I found this Wiki Article that say:

A business rules engine is a software system that executes one or more business rules in a runtime production environment.

The rules might come from any aspect of the business like The rules might come from legal regulation (“An employee can be fired for any reason or no reason but not for an illegal reason”), company policy (“All customers that spend more than $100 at one time will receive a 10% discount”), or other sources. A business rule system enables these company policies and other operational decisions to be defined, tested, executed and maintained separately from application code.

Rule engines typically support: Rules, Facts, Priority (score), Mutual exclusion, Preconditions

The goal of EZ-Rules Framework is to support those features of a Rule Engine.

Our Rule Definition

There is a lot of information about how a Rule can be implemented, let’s mention our vision and implementation of a rule as resume. So in our framework a rule:

  • Is Stateless
  • Is annotated with @Rule
  • Have a priority that define the order of executions of the rules inside a group
  • Have one condition method and at least one action method that will define the behavior of the rule. See annotation @When and  @Then
    • Action methods inside the rule can be prioritize using the priority attribute in the @Then annotation
    • Action method can have any number of parameters. We call those parameters Exchange (see documentation)
    • Action method can have ExchangeManager class as parameter that allow the rule to manage the exchanges (see documentation)
    • Action method can have parameters annotated as @Callback that allow to inject a callback context into the method (if a method is annotated as callback then is become a precondition to the rule to be execute, if the callback is missing the execution will fail).
  • Can have a group associated using the annotation @Group
    • A group have an strategy to run. An strategy can be:
      • Execute all: Meaning the precondition of all rules in the group need to be accepted in order to execute the rule action
      • Stop at first: Meaning that the first group get accepted will be executed and any of the rules after the group can be executed
  • Is thread safe

Getting Started

Build from Git Repository

EZ-Rules is an open source framework. In order to build it you will need Git, Maven and Java installed in your local computer. Alternatively you can use a develop tool (like Eclipse) that normally have support for Git.

To clone the repository from the command line use:

This will install the lasted SNAPSHOT version in your local repository.

Using from maven repository

Creating Rules

Before staring with rule definition samples let talk about some important pieces of the framework related with the rule declaration.

Annotations

@Rule

@Rule annotation allow to mark a POJO class as a Rule class.

The @Rule annotation allow the user to define the priority of the rule, using the priority parameter you can define the order of the rule evaluation

@When

@When annotation allow to mark the conditional method that will decide if the rule need to be executed or not. This method can return 3 different values:

  1. boolean
  2. Boolean
  3. WhenEnum

Depending of the result of the “When” annotated method the rule will:

  • Be executed if the method return true, WhenEnum.ACCEPT
  • Skipped if the method return false, WhenEnum.REJECT

@Then

@Then annotation allow to define the methods in  the rule that will execute the rule action. This method should be void, you can have as many method in the rule annotated with this annotation as you need.

The @Then annotation allow the user to define the priority of the execution, using the priority parameter you can define the order of the “when” methods execution inside the rule. Important, the priority of this method doesn’t affect the priority of the Rule.

@Callback

@Callback annotation allow the user to pass a callback object to either the condition (@Then) of the action (@When) methods. This is useful to inject code into the Rule that allow an external call from inside the rule execution.

To declare a callback you simple need to annotate a class with the annotation

To use the callback inside the rule you can do this:

@GroupDefinition

@GroupDefinition annotation allow to mark a class as Group metadata. It allow to define the execution strategy (Execute All, Stop First Execute for now that is the default implementation). To define a group of rules you need first to define the group metadata using this annotation and after annotate the rule with the corresponding group definition (see @Group annotation.).

Sample of a Group Definition:

@GroupKey

@GroupKey annotation allow to define a grouping key for groups and rules. A rule can be associated to a group, also a group can be contained in another group, this annotation is useful when you want to control the group key of a Rule or a Group at runtime.

Sample of how to use it:

@ParentGroupKey

@ParentGroupKey annotation allow to define a grouping key parent for groups. Using this annotation a group can specify what is the parent group. A null value mean that the group will be associated to the rule engine root.

@Group

@Group annotation allow group a rule into an specific group. The group annotation expect as parameter the group definition in order to know how to group the rules.

A group have a priority that will compete with the rules and groups at the same level. Also inside the group the priority will be use to decide the order of the execution.

@Priority

@Priority annotation allow to define a dynamic way to define the rule priority. In order to dynamically calculate the priority of the rule you need to annotate a method of the rule with this annotation.

Important, priority method is called when the engine start and after that isn’t getting call anymore, isn;t possible to change the rule priority once the rule is fully initialize at this point.

@Exchange

@Exchange annotation allow you to define a named context you want to inject in one parameter. The injection framework have two ways to inject the parameters in the @When and @Then annotated method:

  • By Type: The engine will look in the type of the parameters and will inject the first exchange parameter that is assignable to the parameter type
  • By Name: Using the @Exchange annotation you can specify wish exchange parameter you want to link to the parameter. This one is really useful when you want to match collection, maps etc where specifying  the type contained is ambiguous some times.

 

Exchanges

Exchanges is the mechanism to pass parameters to  the rule. When a rule is execute you can pass a list of parameter that are dynamically binding to the rule flow method by type or by name. Also the rules can contribute back to the exchange using the EchangeManager interface.

Using the exchange manager a rule can execute CRUD operations to the global exchange in the rule execution context.

Example of exchange by type:

Example of exchange by name:

Example of exchange using the exchange manager:

Executing Rules

Let’s show all pieces working together.

First create a simple rule that will receive a Boolean indicating if can be evaluated or not and a message that will get printed based if evaluated.

Creating the rule:

Main application:

Console output:

Conclusion

The rule engine we’re creating has been use already in two company. We advice the developer to try Drools or any other of the big and well established rule frameworks available as a first choice but if you need a lightweight rule engine framework you should really consider this library.

You can see the project in GitHub (see references for all the link) and you’re welcome to contribute with changes to the repo.

In the repository you’ll find 100+ unit test that will help you to understand how the engine work, also there is a sample project where you can see some examples with different features supported by the framework

References

Business rules engine:  Business rules engine @ Wiki

Repository: EZ-Rules @ GitHub

Releases: EZ-Rules Releases @ GitHub

Continuous integration: Build Jenkins job @ CloudBees

Licensing: MIT License