Skip to content

defining rules

Mahmoud Ben Hassine edited this page May 23, 2017 · 23 revisions

Introduction

Most business rules can be represented by the following definition:

  • Name: a unique rule name within a rules namespace
  • Description: a brief description of the rule
  • Priority: rule priority regarding to other rules
  • Conditions: set of conditions that should be satisfied given a set of facts in order to apply the rule
  • Actions: set of actions to perform when conditions are satisfied (and that may add/remove/modify facts)

Easy Rules provides an abstraction for each of these key points to define business rules.

The key API in Easy Rules is the Rule interface:

public interface Rule {

    /**
    * This method encapsulates the rule's conditions.
    * @return true if the rule should be applied given the provided facts, false otherwise
    */
    boolean evaluate(Facts facts);

    /**
    * This method encapsulates the rule's actions.
    * @throws Exception if an error occurs during actions performing
    */
    void execute(Facts facts) throws Exception;

    //Getters and setters for rule name, description and priority omitted.

}

The evaluate method encapsulates conditions that must evaluate to TRUE to trigger the rule.

The execute method encapsulates actions that should be performed when rule's conditions are satisfied.

You can define rules in two ways:

  • By implementing the Rule interface or extending the BasicRule class
  • Adding annotations on a POJO

Defining rules by extending BasicRule

Easy Rules provides a simple implementation of the Rule interface named BasicRule. This class implements most of methods defined in the Rule interface. You can extends this class and override evaluate and execute methods to provide your conditions and actions logic. Here is an example:

public class MyRule extends BasicRule {

    @Override
    public boolean evaluate(Facts facts) {
        //my rule conditions
        return true;
    }

    @Override
    public void execute(Facts facts) throws Exception {
        //my actions
    }

}

Defining rules using annotations

Easy Rules provides the @Rule annotation that can turn a POJO into a rule. Here is an example:

@Rule(name = "my rule", description = "my rule description")
public class MyRule {

    @Condition
    public boolean when(@Fact("fact") fact) {
        //my rule conditions
        return true;
    }

    @Action(order = 1)
    public void then(Facts facts) throws Exception {
        //my actions
    }

    @Action(order = 2)
    public void finally() throws Exception {
        //my final actions
    }

}

The @Condition annotation marks the method to execute to evaluate the rule conditions. This method must be public, may have one or more parameters annotated with @Fact and return a boolean type. Only one method can be annotated with @Condition annotation.

The @Action annotation marks methods to execute to perform rule actions. Rules can have multiple actions. Actions can be executed in a specified order using the order attribute. By default, the order of an action is 0.

Composite rules

Easy Rules allows you to create complex rules from primitive ones. A CompositeRule is composed of a set of rules.

This is typically an implementation of the composite design pattern.

A composite rule is triggered if all conditions of its composing rules are satisfied. When a composite rule is applied, actions of all composing rules are performed in the natural order of rules which is rules priorities by default.

To create a composite rule from two primitive rules, you can use the following snippet:

//Create a composite rule from two primitive rules
CompositeRule myCompositeRule =
    new CompositeRule("myCompositeRule", "a composite rule");
myCompositeRule.addRule(myRule1);
myCompositeRule.addRule(myRule2);

//Register the composite rule as a regular rule
Rules rules = new Rules();
rules.register(myCompositeRule);

RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, someFacts);

Rules priorities

Each rule in Easy Rules has a priority. This represents the default order in which registered rules are fired. By default, lower values represent higher priorities. To override this behavior, you should override the compareTo method to provide a custom priority strategy.

  • If you decided to extend the BasicRule class, you can specify rule priority at construction time or by overriding the getPriority() method

  • If your rule is a annotated POJO, you should annotate the method that provides priority with @Priority annotation. This method must be public, have no arguments and return an Integer type.

Using the Rules API

A set of rules in Easy Rules is represented by the Rules API. IT can be used as follows:

Rules rules = new Rules();
rules.register(myRule1);
rules.register(myRule2);

Rules represents a namespace for registered rules. Hence, each registered rule must have a unique name within this namespace.