I have to build a dynamic rules engine in say, Java, where a user can define a certain list of filters and trigger a certain event based on them. The rules will be a long chain of conditions, such as:
if
condition1 AND (condition2 OR condition3) AND condition4
then
trigger(event)
where conditionN is any operation based on the attribute for a business object. Example: a string can have an operation - endsWith or a number can have operations greaterThan.
The problem is, this list of rules will not be hard-coded and has to be fetched dynamically from a database (a separate web UI will update this database with the rules) and run against an entity and then trigger the appropriate action on the entity.
What's the best way to approach this kind of problem and write a scalable and high-performant program for this?
I am currently thinking of building expressions in Spring Expression Language (SpEL) and storing them in DB as strings and then while running the program, fetching this column and running them against my domain object.
// Fetch rule and action from DB
rule = rs.getString("rule"); // Rule in SpEL
action = rs.getString("action"); // Action method name
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(rule);
boolean result = (String) exp.getValue(obj, Boolean.class); // Run expression against domain object `obj`
if (result) action();
I am currently not sure if this is the best way for doing things and if it will scale and be extensively customizable or not.
For the above approach, then rule string needs to built by parsing user input. I was also thinking about storing rules as an XML document:
<Rule>
<Filter>
<Operation name="or">
<Operand>
<Operation name="lessThan">
<Operand>${numAttribute}</operand>
<Operand unit="percentage">5.05</operand>
</Operation>
</Operand>
<Operand>
<Operation name="equals">
<Operand>${stringAttribute}</Operand>
<Operand>IN</Operand>
</Operation>
<Operand>
</Operation>
</Filter>
<Action>
actionName
</Action>
</Rule>
However, with this scenario, I am not sure how to proceed after parsing the XML and how to run the operations dynamically based on the described values.
I would appreciate any ideas of the aforementioned ones or a totally new way to solve this problem. I understand it's a huge application but need clarity on how to start. I believe the biggest problem is how to run user inputs statements as Java code? I know a little bit about reflection but I am not sure if it's meant to solve this problem and if it should be used considering it has its drawbacks in areas of performance.