What are Easy Rules?

Easy Rules is a simple and powerful Java Rules engine that provides the following features:

  • Lightweight framework and easy to learn API
  • Pojo-based development and annotation programming model
  • Define abstract business rules and easily apply them
  • The ability to create composite rules from simple rules
  • Support for the ability to define rules using expression languages such as MVEL and SpEL

Runtime environment

Easy Rules is a Java library that runs on Java 1.7 and above.

Maven rely on

<properties>
    <easy.rules.version>4.1.0</easy.rules.version>
</properties>
<! -- Easy rules execution engine -->
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-core</artifactId>
    <version>${easy.rules.version}</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-mvel</artifactId>
    <version>${easy.rules.version}</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-spel</artifactId>
    <version>${easy.rules.version}</version>
</dependency>
<! -- Easy rules execution engine -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>
Copy the code

Programming model based on MVEL expression

Define the rules

Most business rules can be represented by the following definitions:

  • Name: a unique rule Name in a namespace
  • Description: Brief Description of the rule
  • Priority: Priority relative to other rules
  • Facts are immediately available for data to be processed
  • Conditions: A set of Conditions that must be met in order to apply a rule
  • Actions: A group of Actions that are performed when a condition is met

Easy Rules provides an abstraction for each key point to define business Rules.

Entity class user

import lombok.Data;

@Data
public class User {
    private Integer age;
}
Copy the code

Run the demo

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.mvel.MVELRule;

import java.util.HashMap;
import java.util.Map;

public class MTest {

    public static void main(String[] args) {
        // Rules engine
        RulesEngine rulesEngine = new DefaultRulesEngine();
        / / rules
        MVELRule ageRule = new MVELRule()
                .name("test rule1")
                .description("test demo rule1")
                .priority(1)
                .when("user.age > 18")
                .then("map.put('code',200); Map. Put (' MSG ',' adult ');");

        Rules rules = new Rules();
        rules.register(ageRule);

        Facts facts = new Facts();

        Map<String,Object> map = new HashMap<>();
        User user = new User();
        user.setAge(19);
        facts.put("user", user);
        facts.put("map", map); rulesEngine.fire(rules, facts); System.out.println(map); }}Copy the code

The results

14:01:21.699 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
14:01:21.704 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'test rule1', description = 'test demo rule1', priority = '1'}
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='map', value={}}
14:01:21.705 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='user', value=User(age=19)}
14:01:21.723 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
14:01:21.767 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'test rule1' triggered
14:01:21.817 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'test rule1'Performed successfully {MSG = Adult, code=200}
Copy the code

RuleListener RuleListener

public class CustomRuleListener implements RuleListener {
    @Override
    public boolean beforeEvaluate(Rule rule, Facts facts) {
        System.out.println("---CustomRuleListener------beforeEvaluate-----");
        return true;
    }

    @Override
    public void afterEvaluate(Rule rule, Facts facts, boolean b) {
        System.out.println("---CustomRuleListener------afterEvaluate-----");
    }

    @Override
    public void beforeExecute(Rule rule, Facts facts) {
        System.out.println("---CustomRuleListener------beforeExecute-----");
    }

    @Override
    public void onSuccess(Rule rule, Facts facts) {

        System.out.println("---CustomRuleListener------onSuccess-----");
    }

    @Override
    public void onFailure(Rule rule, Facts facts, Exception e) {
        System.out.println("---CustomRuleListener------onFailure-----"); }}Copy the code
  • BeforeEvaluate This method is executed before the @condition modified method is executed. If this method returns false, the current rule is skipped.

  • AfterEvaluate This method is executed after the @condition modifier is executed.

  • BeforeExecute This method is executed before the @Action modified method is executed.

  • The onSuccess method is executed after the @Action modified method is executed.

  • OnFailure Executes when an exception occurs in a method that executes the @Action modifier.

In the rulesEngine. The fire (rules and facts); Register rule listeners before

((DefaultRulesEngine) rulesEngine).registerRuleListener(new CustomRuleListener());
Copy the code

RulesEngineListener

public class CustomRulesEngineListener implements RulesEngineListener {
    @Override
    public void beforeEvaluate(Rules rules, Facts facts) {
        System.out.println("---CustomRulesEngineListener------beforeEvaluate-----");
    }

    @Override
    public void afterExecute(Rules rules, Facts facts) {
        System.out.println("---CustomRulesEngineListener------afterExecute-----"); }}Copy the code
  • beforeEvaluateThe method is executing@ActionThe decorated method is then executed. Execute before RuleListener
  • afterExecuteThe method is executing@ConditionThe decorated method is executed before. Execute after RuleListener

In the rulesEngine. The fire (rules and facts); Register rule engine listeners before

((DefaultRulesEngine) rulesEngine).registerRulesEngineListener(new CustomRulesEngineListener());
Copy the code

Rule engine initialization parameters

  • When the skipOnFirstAppliedRule is true, starting with the first rule, matching one rule skips subsequent rule matches, failing which the rule continues

  • If skipOnFirstFailedRule is true, subsequent rule matches will be skipped if an exception occurs during the execution of @Action

  • SkipOnFirstNonTriggeredRule is true, from the first article, match a will to perform, does not match the skip

  • If rulePriorityThreshold is greater than the specified priority, no match is performed

 RulesEngineParameters parameters = new RulesEngineParameters()
 parameters.skipOnFirstAppliedRule(true);
 parameters.skipOnFirstFailedRule(true);
 parameters.skipOnFirstNonTriggeredRule(true);
 parameters.priorityThreshold(3);
 
 RulesEngine rulesEngine = new DefaultRulesEngine(parameters);
Copy the code