Well, I am sure you have heard enough about rules and rule engine. But if you are scavenging for a quick start tutorial with simple example then you are on the right place. The example supplied with this article uses jRuleEngine v 1.3. Let me first throw few lines out on the rules and rule engine just to fill you.
What is a rule?
Rule is a business rule that validates the data under certain circumstances.
Simply rule is nothing but the business logic that we code in our service classes using if else statements.
Lets take a typical shopping cart as an example and say if couponCode.equals(“TRY10”) then apply 10% off of the total amount in the cart. So checking the various coupon codes is one rule inside the OrderService class. Applying 10% off is an action that goes with the rule if it is applicable.
Now imagine, coding one dozen coupon codes and applicable actions around it inside the service class. This is a very simple scenario but enough to start thinking of kicking this logic out of service class. This is where we would end up using the rule engine so that business can drive these variants without code changes.
What is a rule engine?
A rule engine is simply an interpreter of these rules or if/then statements. Theoretically you give the input to this rule engine, tell the set of rules to apply on the input and expect the desired output.
So now these rules can be defined in external files in the format of xml and other proprietary formats that adhere to RuleML standard or simply drive the rules from database tables.
Enough explanation, let’s get our hands dirty
So say this ecommerce company makes various seasonal coupons available for their customers. Just for the brevity we will consider each coupon has expiration date and discount percent. So the shopping cart application should be managing these coupons more effectively in order to cope with business ideas. It’s time to bring in the rule engine.
First thing first
Let’s get started with rules. We could drive these rules through 2 ways, xml or database tables as I mentioned earlier.
Loading rules through XML
Take a look at the code snippet below
<rule-execution-set>
<name>CouponRule</name>
<description>Rules to apply coupon discounts</description>
</rule-execution-set>
We just defined a rule execution set with name and description to look up later.
Now we could use synonymn element as name itself suggests, define a handler for any input objects that could be referred inside the rule xml and rule engine.
<synonymn name="order" class="com.rule.model.Order" />
<synonymn name="coupon" class="com.rule.model.Coupon" />
Now we could define a rule using rule element like below,
<rule name="Rule10" description="10% discount coupon rule" >
<if leftTerm="coupon.getName" op="=" rightTerm="TRY10" />
<if leftTerm="coupon.isValid" op="=" rightTerm="true" />
<then method="order.applyCoupon" arg1="10.00" />
<then method="order.setComment" arg1="Applied 10% off." />
</rule>
What we are trying to do with the above rule lines is, if coupon name is TRY10 and order date (assume) today is before or equals to expire date then apply 10% off of total order amount of the cart and set the comment. For the brevity I used comment but practically it could be a logic to mark the cart that coupon has been applied already. That’s pretty much it for one coupon rule.
Now if you have tens or hundreds of coupons then you will end up writing that many rule elements inside this xml.
Loading rules through database tables
In theory rule in xml files should be good enough but not enough when it comes to manageability on long run. Just imagine adding hundreds of coupon rules would simply bloat the xml. Secondly xml changes would require an application restart. Using tables would bring better manageability of rules and makes it more dynamic.
OK, how do we create these rule tables and how do we define these rules in them?
Rules Class Diagram
If you look at the jrule engine source code you would see these classes going on in their rule package.
A straight translation of the above classes would result in tables shown below in the ERD diagram. These tables represent a simple conversion of the elements defined in xml into table.
Well we could go one level up and define the rule execution set to hold these rules.
Now it is just a matter of writing insert/update statements into these tables but you could build the UI in your application to manage these rules as well. If you decide to have a UI for business to manage these rules then you will have to come up with relational tables around the required properties. I will try to cover that in my next article.
Rest of the code around rule api’s is simple and self explanatory in this example so I wouldn’t bother digging into it.
If you look into this convenience wrapper class RuleInfrastructureServiceImpl, you will notice there are utility method to get the ServiceManager, RuleAdministrator and several overloaded createRuleExecutionSet methods.
The createRuleExecutionSet could be called with input stream to load rules from xml where as called with RuleImpl object to load rules off of tables.
Ultimately you will need to create a rule session to execute rules. A rule session is a communication connection between your application code and rule engine. In theory each rule session represents one execution rule set.
It is always best practice to use a stateless rule session over stateful in most scenarios considering the performance bottlenecks.
The OrderService’s applyCoupon method would take three parameters Order, couponCode entered by the customer and rule session object.
Final Note
Using rule engine would simplify lot of business operation around the application but would definitely takes 2 plus 2 cents to design and build such rules interfaces in the application.
Reference
Download the source code for the example used in this article.
Hi ,
ReplyDeleteThanks for your detail explanation on implementation of JRuleEngine.
It looks like your source jar "MyRules.jar" is corrupted and unable to extract it.
Can you please upload the new copy as i need it for my poc.
Once again thank you very much for your contribution.
Thanks,
Murali
Thank you for useful info.. I am new to JRule so please upload the source code for the above example there is no source code in the link Download above.
ReplyDeleteGreat explanation
ReplyDelete