-
Notifications
You must be signed in to change notification settings - Fork 1.1k
expression language support
Easy Rules provides support for defining rules with MVEL, SpEL and JEXL.
The support for each expression language is provided through a dedicated module: easy-rules-mvel
, easy-rules-spel
and easy-rules-jexl
. These modules provide APIs to define conditions, actions and rules. Please note that conditions and actions written in SpEL should use the #{ ... }
template.
EL providers have some differences in behaviour. For instance, when a fact is missing in a condition, MVEL throws an exception while SpEL silently ignores that and returns false
. Therefore, you should be aware of these differences before choosing which module to use with Easy Rules. Easy Rules does not (and should not) take into account these differences. As far as the rules engine is concerned, it should try evaluate a condition expecting it to return true
or false
. For any runtime exception (missing fact, typo in the expression, etc), if one EL provider returns false while another throws an exception, Easy Rules will act accordingly (More details in the Error handling in rule definitions section).
Conditions, actions and rules are represented respectively by the MVELCondition
/SpELCondition
/JexlCondition
, MVELAction
/SpELAction
/JexlAction
and MVELRule
/SpELRule
/JexlRule
classes. The following is an example of rule definition using MVEL:
Rule ageRule = new MVELRule()
.name("age rule")
.description("Check if person's age is > 18 and marks the person as adult")
.priority(1)
.when("person.age > 18")
.then("person.setAdult(true);");
You can also define a rule in a descriptor file and use the MVELRuleFactory
/SpELRuleFactory
/JexlRuleFactory
to create a rule from the descriptor. Here is an example of an MVEL rule defined in YAML format in alcohol-rule.yml
:
name: "alcohol rule"
description: "children are not allowed to buy alcohol"
priority: 2
condition: "person.isAdult() == false"
actions:
- "System.out.println(\"Shop: Sorry, you are not allowed to buy alcohol\");"
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
MVELRule alcoholRule = ruleFactory.createRule(new FileReader("alcohol-rule.yml"));
You can also create multiple rules at the same time from a single file. For instance, here is a rules.yml
file:
---
name: adult rule
description: when age is greater than 18, then mark as adult
priority: 1
condition: "person.age > 18"
actions:
- "person.setAdult(true);"
---
name: weather rule
description: when it rains, then take an umbrella
priority: 2
condition: "rain == true"
actions:
- "System.out.println(\"It rains, take an umbrella!\");"
To load these rules into a Rules
object, you can use the following snippet:
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
Rules rules = ruleFactory.createRules(new FileReader("rules.yml"));
You can find a complete example of how to use Easy Rules with MVEL in the shop tutorial.
Easy Rules provides support to load rules from a JSON descriptor as well. You can use the JsonRuleDefinitionReader
with the MVELRuleFactory
as follows:
MVELRuleFactory ruleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader());
Please note that rules descriptors should be defined as an array of JSON object (each object defines a rule) even if a single rule is defined. Here is the previous alcohol-rule
expressed in JSON:
[
{
"name": "alcohol rule",
"description": "children are not allowed to buy alcohol",
"priority": 2,
"condition": "person.isAdult() == false",
"actions": [
"System.out.println(\"Shop: Sorry, you are not allowed to buy alcohol\");"
]
}
]
For any runtime exception that may occur during condition evaluation (missing fact, typo in the expression, etc), the engine will log a warning and consider the condition as evaluated to false. It is possible to listen to evaluation errors using RuleListener#onEvaluationError
.
For any runtime exception that may occur while performing an action (missing fact, typo in the expression, etc), the action will not be performed and the engine will log an error. It is possible to listen to action performing exceptions using RuleListener#onFailure
. When a rule fails, the engine will move to the next rule unless the skipOnFirstFailedRule
parameter is set.
Easy Rules is created by Mahmoud Ben Hassine with the help of some awesome contributors
-
Introduction
-
User guide
-
Tutorials
-
Get involved