JRules - A brief overview
Listen to this article
As requested, my brief overview of JRules. I'm sure I will have failed to answer many questions so feel free to ask. If I know the answer, I'll add it to the entry, othwerwise I'll either cop out and say I don't know or go and find out. As always, if I've made a mistake or three, feel free to point them out.
First off, I found JRules very easy to use. It comes with very good documentation. As I mentioned in a previous entry, foremost in my mind was to prove testability. I can safely say that rules can be fully unit tested. So there are no excuses! ;-)
Like many rule engines, JRules usess a Rete network. The cool thing about the Rete algorithm is that rules with similar conditions (or subsets of conditions) are identified and evaluated together meaning that the conditions need only be tested the minimum number of times. This differs from java coded rules where typically every condition in every rule must be evaluated regardless of whether we might already have tested for it in previous rule.
The centre (no, this is not a spelling mistake) of the programmatic world in JRules is the rule engine (IlrContext) also known as a context. The context holds a set (IlrRuleset) of rules (IlrRule). The context also holds facts. Facts are simple java objects and, as the name implies, are the things we know about the state of the processing "world". As you add (assert) facts about the state of your "world", the rule engine updates the agenda. At any given point, the agenda holds the rules that have conditions matching the current state and are therefore ready for firing.
Once a rule has fired, it is removed from the agenda and will not be made available for firing unless it, or another rule, modify the current state such that the rule conditions would once again be satisfied. This is pretty neat as it means you can have rules assert facts that cause other rules to fire.
Rules can be assigned a priority to assist in determining the firing order. The specific ordering rules are clearly documented so I wont repeat them here.
Rules can be grouped into "packets". Packets can then be referenced (and executed) by name. This can be very useful if you have certain classes of rules that you know you will/wont need during processing and therefore wish to programmaticaly enable/disable at runtime. JRules 4.5 also provides a RuleFlow mechanism which is supposedly the "preferred" method of achieving the same thing. I must admit that in our case, ruleflows didn't seem appropriate so we have so far stuck with packets.
There is one more facility for filtering rules from the agenda. These firing filters are applied to rules whos conditions have already been evaluated and are in the agenda. This differs from packets and ruleflows which selectively add/remove rules prior to evaluation.
Rulesets support in, out and inout variables which are then available to all rules within the ruleset. This is one mechanism you could use to parameterise your rules.
JRules out-of-the-box provides three languages in which rules can be written:
- IRL - ILog Rule Language;
- TRL - Technical Rule Language; and;
- BAL - Business Action (Natural) Language.
I started off using IRL as it was the language given in the documentation examples. It's a fairly low-level language. I think from a geeks perspective it's the one to start with as it gives you a good understanding of what actually goes on. IRL can be written using the text editor of your choice. A simple example of IRL might look like:
when {
?order: Order(product == Product.CHAMPAGNE);
Customer(state == State.VIC; status == CustomerStatus.GOLD) from ?order;
} then {
?order.applyDiscountPercentage(15.00);
System.out.println("Discount applied!");
}
This essentially says, whenever an order for champagne is raised by gold customers in victoria, apply a 15% discount and print a message to that effect.
Each condition in the when clause is evaluated in the order declared. The conditions are AND'ed together. If the condition(s) are met, any statements in the then clause are executed when the rule is fired. For completeness, there is also an else clause.
As you can probably see, the IRL is a Java-like language supporting, as far as I can tell, almost all usual java syntax (including imports) plus the additional syntax required for describing rule conditions.
TRL is pretty much the same as IRL but is more verbose. For example:
when there exists an Order(product == Product.CHAMPAGNE)...
Strictly speaking, the BAL is actually an example language that demonstrates how you can build your own language on top of the underlying languages. Having said that, the BAL is almost feature complete and many businesses will choose it over the TRL and IRL. The intention is that business people can write in BAL. In actualality, I see this being about as likely to happen as business people using Crystal Reports to write custom reports. If you can make it happen, great but I very much doubt it. However, BAL is much easier to read especially for business people and even for developers. So when, as a developer, you need to validate that the rule you've just written is correct, BAL is a god send. Even mildly complex rules are quite hard to follow in raw IRL and, for that matter, TRL.
BAL also requires a mapping layer between your Java objects and natural language. This is so that instead of writing order.getTotal() we can instead use the total amount of the order. On an agile project that is ramping up, I can see this as being an small but certainly not insurmountable issue due to the ever changing domain model.
JRules comes with a GUI Editor that allows you to maintain rules in any of the supported languages. While it is possible to create rules by hand in IRL and stored as plain text files, TRL and BAL require the GUI. The rules are stored in a repository (directory structures) that can then be exported to an IRL file for use by an application. Again, Not so much of a problem really but being forced to point and click when I really just want to type is very frustrating. If I could ask for one thing, it would be the ability to edit BAL rules in my editor of choice and then import them into the repository.
BAL and TRL are both converted to IRL. IRL can be converted back into TRL. Unfortunately the conversion from BAL to IRL is a one-way street. Taking a look at the generated IRL was quite an eye-opener. The rule editor converts BAL into IRL that is almost impossible to understand by a human.
From a purely technical perspective, it matters little what language the rules are written in as they end up as IRL which is then parsed and executed by your application. Loading and running a test requires only one jar file (jrules-engine.jar) and can be as simple as:
public void testEngineIntegration() {
// Define a simple rule
final String rule = "rule TestRule\n" +
"{\n" +
" when\n" +
" {\n" +
" not String();\n" +
" }\n" +
" then\n" +
" {\n" +
" assert Integer(57);\n" +
" }\n" +
"};";
// Parse the rule
IlrRuleset ruleset = new IlrRuleset();
assertTrue("Rule parsing failed", ruleset.parseReader(new StringReader(rule)));
// Create a context (rule engine)
IlrContext context = new IlrContext(ruleset);
// Execute the rule and ensure it was actually run
assertEquals(1, context.fireAllRules());
// Check the final state matches the expected state
Enumeration enum = context.enumerateObjects();
assertNotNull(enum);
assertTrue(enum.hasMoreElements());
assertEquals(57, ((Integer) enum.nextElement()).intValue());
assertFalse(enum.hasMoreElements());
}
You can also load rules directly from the repository if you wish. So far we haven't attempted this and for the time being at least it's not a high priority as we will be loading the ruleset from the exported script.
The repository, apart from being a pain to use, has some other mildly annoying issues when working in an agile team. These are mainly to do with locking rules for editing. The rule editor allows you to create rule packages (not to be confused with packets) and it is only at these levels that locking is possible. Again, not too much of an issue. Besides, you will quickly find your rules unmanageable if you don't group them at all. Packages are also useful if/when writing ruleflows. Remember however that these packages are purely logical and affect only the names of the generated rules. Something you will most likely rarely have to worry about anyway.
Generally, I would recommend keeping your rules as simple as possible. If your find your rules blowing out to four pages, stop and think again. Rules can and should be decomposed into smaller rules. James Ross has been reading a great book on the subject, Principles of the Business Rule Approach, which he says is a must read for anyone embarking on business rules analysis.
Comments
Thanks for the review. Your review matches my experience with JRules. As a 20 year vet programmer I also sometimes find "clicky" IDEs frustrating.
Have you looked at the open source riles engine JESS? (JESS in Action by Enest Friedman-Hill).
It uses the Rete algorithm also. I have done experimentation with the JRules evaluation product. If you are not using the JRules IDS/Repository then you might find that JESS does what you need at a much lower cost.
Gary Hackathorn
Posted by: Gary Hackathorn | March 11, 2004 06:45 AM
Hi Gary,
I have actually looked at (and used) JESS on other projects and more recently drools. The choice of JRules on this project was largely political so I didn't have any say in the matter. Again, the use of the IDE and the BAL was largely political as well.
I love rules engines so hopefully the next project will allow me to use either JESS or Drools :-)
Thanks for the feedback too.
Cheers,
Simon
Posted by: Simon Harris | March 11, 2004 07:07 AM
I have heard that the inputs to the engine (your domain objects or adapters, whatever) MUST implement some interface(s) to accomodate the callbacks necessary for Rete to work properly. Is this true? If so, how invasive are the interfaces?
Posted by: Matt | March 12, 2004 11:46 PM
Not that I'm aware of. The inputs (or facts) don't have to implement anything. They can be simple POJOs, remote EJBs, whatever. The conditions and actions are essentially defined in java so it's really a matter of calling whatever methods happen to be on your objects.
Maybe there is some other mechanism of which I'm not aware but even if then, it's certainly not a requirement.
HTH,
Simon
Posted by: Simon Harris | March 13, 2004 06:21 AM
"The cool thing about the Rete algorithm is that rules with similar conditions (or subsets of conditions) are identified and evaluated together meaning that the conditions need only be tested the minimum number of times"
And, as we know, that means that we must ensure that the conditions do not result in a state change. ;)
Posted by: Mike Melia | March 19, 2004 10:00 PM
Great article!
Posted by: Tim Johnston | April 30, 2004 02:02 AM
By the JRULES 4.x/5.x/6.x satisfies the JSR-94 1.x
Posted by: Krishna | March 5, 2005 08:12 AM
Thanks for a very informative article! Is it possible to have alternative mappings of the natural language to Java objects? For example: can "the total amount of the order" be mapped to method getTotal() of the Order class in one application and to method fetchAmount() of the ShoppingCart class in another application? In other words does JRules assume that all applications where rules are deployed use same Java classes?
Posted by: Branimir Dolicki | April 15, 2005 02:14 AM
The simple answer is yes...or is it no...I'm confused hehehe. But seriously, one BAL repository is, as far as I'm aware, bound to a single set of java classes. If you wanted to have the same rules over a different set of java classes, you'd have to copy the repository and re-map the model.
It is actually possible to generate the repository mapping files so this could be one option for you.
Cheers,
Simon
Posted by: Simon Harris | April 15, 2005 02:24 AM
Hi,
I would like to get more information about JRules. I start working with it and i have very basic knowledge. Can you help me and direct me to a book or "pdf" file. I'll really appreciate your help.
Regards,
Tzvika
Posted by: tzvika | July 26, 2005 08:53 PM
Hi guys,
Can someone direct me to documentation examples of the JRules ("pdf" or something...)
Tzvika
Posted by: Tzvika | July 26, 2005 09:24 PM
BTW, if you go out to my web site, I've actually done an in-depth review of JRules several times now. Also some other rulebased systems. (My personal favorite is OPSJ from PST) All for InfoWorld, not very technical but at the CEO / CTO level. Why InfoWorld and not JavaWorld? Because InfoWorld pays better and I get better exposure. :-) Seriously, though, check out
http://www.kbsc.com/publications.html
Right now I'm looking at one of the originals, Mind Box, formerly known as Inference Corporation, who came out with ART and ART IE in the 1980's and early 90's. They aren't quite as artsy as either JRules or Blaze Advisor, but they do have what is maybe the best all-around package for Mortgage companies. Enjoy.
SDG
jco
Posted by: James Owen | August 20, 2005 03:20 AM
One question I have is about their licensing. I have inherited a system from one of the BIG 5 consulting companies with barely any documentation and 2 years of junk.
What is the JRULES licensing scheme, in terms of both deployment and development.
Also I do not see any real installations. In my application there is 1 ILR file and one jrules-engine.jar file. I am not sure where the license file is hidden.
Any help I would really appreciate.
Posted by: Anonymous | December 9, 2005 02:03 PM
hi,
i do the work on ILOG JRules.i feel some problem related to this.ie-
Q1-- Can i write different Rules, Main class ,Setup Rules etc. together(in single page)? in given Example(in given ILOG S/W) thise things are write different files.how we connect these files together?
Q2---I use DBTOOL GUI( in ILOG Jrules S?W) ,connect the database ,establish the relationship between two table field .after connection of batabase this generate java class but not generateILR file, why not?
Q3- In ilr file we find our rules. .these files generated by developer(BY coding)? Not generated By DBTool .
hilp me any body.
Regards:
ashish rai
Posted by: Ashish | June 25, 2006 08:42 PM
Hey,
i need help with jrules 5 gui.
this is a bug i cannot solve.
i am using jrules 5 gui tool
when building a decition table, i try to pick a variable from the drop down list, i can see the variable but cannot pick it, if i pick it, i get "integer is" line.
did soneone encounterd this problem?
are there fix packs to solve it?
cheers for the help
ishay.
Posted by: ishay | July 30, 2006 07:59 PM