2

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.

int-main
  • 29
  • 2
  • 1
    Consider your users. Unless those users are software engineers or otherwise have a great deal of programming experience, it's highly unlikely that they will have the technical background necessary to cope with the syntax that you're proposing in your XML document or be able to debug it if it breaks. On the other hand, if they are software engineers or they do have programming experience they will probably be extremely irritated about needing to write the rules in XML instead of just being able to write them in a popular, well-known mainstream programming language like Java instead. – Ben Cottrell Feb 01 '20 at 22:47
  • To put it another way, your attempt at solving this problem looks like you're just writing your own programming language, yet using a far less programmer-friendly syntax. When writing a new language you need to consider maintainability of the source that your users are going to write - for example, how will they version-control it? how will they run automated tests against the logic? how will they debug faults? how will they monitor failures? What about an IDE to help write the code? etc. All-in-all, you are probably just better off using an existing programming language instead. – Ben Cottrell Feb 01 '20 at 22:50
  • Instead of going to all the effort to write a whole new language for your rules, perhaps consider just releasing an API or SDK and encouraging users to use that with some popular/existing language like Python/Java instead. – Ben Cottrell Feb 01 '20 at 22:58
  • (1/2) @BenCottrell Thanks for responding. Apologies if I didn't explain the use case properly. The rule engine does not require hand programming by hand. I want to have a web UI which takes HTML forms with dropdowns, take chain of operations that result in boolean output, generate a runnable expression and store it in DB. During runtime, the rule is read from DB, evaluated against the current object and if true does something on the object and if false, does something else. – int-main Feb 02 '20 at 05:12
  • (2/2) I am not expecting anyone to write these rules by hand and I am not sure how to write them in an existing programming language because that sounds to me like hard-coding it again. The plan is to have one application handle generation and updating in DB and one to read, parse and execute the rules. – int-main Feb 02 '20 at 05:16
  • Still, start by thinking about your users - a visual language is still a language and the UX/usability is still just as important. If your users need to do everything through clickable UI forms, then that's still potentially just as difficult and frustrating as writing code directly. Still consider how users will debug the rules, and how they will be able to test them, how the rules will be version controlled, how the system will monitor for errors. I would strongly recommend you put a huge amount of work into trying to design the UX for your users before you worry about the rest of it. – Ben Cottrell Feb 02 '20 at 09:09
  • Also, there is no such thing as "hard coding" - there's no real difference between writing rules in an XML-based DSL versus writing it in a programming language format like Java/Python. Whatever code you are going to write to execute your XML rules could do exactly the same thing using Java instead. Source code is just structured data which is able to represent logic. What you're doing with XML is no different to what you'd do with any other programming language except that there are already loads of existing tools for Java. Again, consider the idea of an API/SDK instead of a DSL. – Ben Cottrell Feb 02 '20 at 09:15
  • 1
    Why must the list of rules not be hard coded? Hard coded rules can still be changed, you just have to re deploy the application when you make the change. The most successful organisations seem to be deploying applications to production many times per day. – bdsl Feb 02 '20 at 10:05
  • Could this answer help you: https://softwareengineering.stackexchange.com/a/376438/209774 . The parsing of the XML would lead to an interpreter pattern, that could then be evaluated with a rule engine that could trigger the events. If you're not familar with interpreter pattern, this question explains how to use it with mathematical expressions: https://softwareengineering.stackexchange.com/a/400047/209774 – Christophe Feb 02 '20 at 17:17

1 Answers1

1

After using two rules engine implementations, I would say Don't go down this path.

Simply create a library that incapsulates the rules as a . jar file and import it into the applications that need to access those rules.

In my experience this is the simple, fast and efficient method of implementing business rules.

kiwiron
  • 2,278
  • 10
  • 13