|
|
|
---
|
|
|
|
layout: docs
|
|
|
|
title: Defining rules
|
|
|
|
header: Defining rules
|
|
|
|
prev_section: user-guide/introduction
|
|
|
|
next_section: user-guide/rules-engine
|
|
|
|
doc: true
|
|
|
|
---
|
|
|
|
|
|
|
|
The key API in Easy Rules is the `Rule` interface:
|
|
|
|
|
|
|
|
```java
|
|
|
|
public interface Rule {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method encapsulates the rule's conditions.
|
|
|
|
* @return true if the rule should be applied, false else
|
|
|
|
*/
|
|
|
|
boolean evaluate();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method encapsulates the rule's actions.
|
|
|
|
* @throws Exception thrown if an exception occurs
|
|
|
|
* during actions performing
|
|
|
|
*/
|
|
|
|
void execute() 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:
|
|
|
|
|
|
|
|
```java
|
|
|
|
public class MyRule extends BasicRule {
|
|
|
|
|
|
|
|
private BusinessData myBusinessData; //data to operate on
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean evaluate() {
|
|
|
|
//my rule conditions
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void execute() 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:
|
|
|
|
|
|
|
|
```java
|
|
|
|
@Rule(name = "my rule", description = "my rule description")
|
|
|
|
public class MyRule {
|
|
|
|
|
|
|
|
private BusinessData myBusinessData; //data to operate on
|
|
|
|
|
|
|
|
@Condition
|
|
|
|
public boolean when() {
|
|
|
|
//my rule conditions
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Action(order = 1)
|
|
|
|
public void then() 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, have no parameters 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.
|
|
|
|
|
|
|
|
<div class="note info">
|
|
|
|
<h5>Actions can be executed in a specified order</h5>
|
|
|
|
<p>You can also define the execution order of actions with the
|
|
|
|
<em>order</em> attribute: <em>@Action(order = 1)</em>. By default, the order of an action is 0.</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
## 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 <a href="http://en.wikipedia.org/wiki/Composite_pattern" target="_blank">composite design pattern</a>.
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
```java
|
|
|
|
//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
|
|
|
|
RulesEngine rulesEngine = aNewRulesEngine().build();
|
|
|
|
rulesEngine.registerRule(myCompositeRule);
|
|
|
|
```
|
|
|
|
|
|
|
|
## 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
|
|
|
|
|
|
|
|
## Rule listener
|
|
|
|
|
|
|
|
You can listen to rule execution events through the `RuleListener` API:
|
|
|
|
|
|
|
|
```java
|
|
|
|
public interface RuleListener {
|
|
|
|
/**
|
|
|
|
* Triggered before a rule is executed.
|
|
|
|
*/
|
|
|
|
void beforeExecute(Rule rule);
|
|
|
|
/**
|
|
|
|
* Triggered after a rule is executed successfully.
|
|
|
|
*/
|
|
|
|
void onSuccess(Rule rule);
|
|
|
|
/**
|
|
|
|
* Triggered after a rule is executed with error.
|
|
|
|
*/
|
|
|
|
void onFailure(Rule rule, Exception exception);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
You can implement this interface to provide custom behavior to execute before/after each rule.
|
|
|
|
To register your listener, use the following snippet:
|
|
|
|
|
|
|
|
```java
|
|
|
|
RulesEngine rulesEngine = aNewRulesEngine()
|
|
|
|
.withRuleListener(myRuleListener)
|
|
|
|
.build();
|
|
|
|
```
|
|
|
|
|
|
|
|
You can register as many listeners as you want, they will be executed in their registration order.
|