Introducing Drools 5
Posted by Brian Sam-Bodden
A Java Rule Engine for the rest of us
For most Java developers the idea of using a Rule Engine evokes thoughts of vendors in suits selling their bosses a complex and expensive piece of software they don’t need and the introduction of something completely foreign and intrusive to their code base. Drools 5 (http://www.jboss.org/drools/) aims to change this perception by bridging the gap between the Java developer and world of Rule-based systems. The Quick and Dirty on Rule Engines
The simplest explanation of what a rule engine is that is a very efficient pattern matcher. It matches data, referred to as “facts” against rules. Rules are simple if-then constructs that operate on the matched data. For example, imagine an example application in which the data is a loan application containing the credit score for the loan applicant. A rule could express a credit score requirement for a loan such as:
“A loan application for ACME loans for which the loan applicant has a credit score lower than 680 will be rejected”
For the context of the this example assume that the following Java classes exist:
Mortgage: Represents a loan product belonging to a lender. It contains amongst other data, the name of the lender providing the loan.
LoanApplication: Represents an application for a specific loan product. It contains information specific to the applicant such as the credit score and the lender associated with the application.
RejectionNotice: Represents a communication to the applicant that the application has been rejected
rule "LowCreditScoreRejection"
dialect "java"
when
mortgage:Mortgage(
lender:lenderName == "ACME"
)
application:LoanApplication(
lender == mortgage.lenderName,
score:creditScore < 680
)
then
application.reject("the score " + score + " is too low. \n" +
"A credit score of at least 680 is required");
insert(new RejectionNotice(application));
end
Listing SAM-1 A simple rule
The rule named “LowCreditScoreRejection” is a typical Drools Rule Language (DRL) rule. It has two parts; the “when” part, also known as the “predicate”, “premise”, “condition” or simply as the “Left-hand side” (LHS for short) and the “then” part or “consequence”, “action”, “conclusion” or “Right-hand side” (RHS)
The Rule Condition
The “when” part or rule condition determines the patterns to be matched. That is, the types and characteristics of the objects that will activate the rule. In the example shown, we are looking to match two objects, an object of type Mortgage and an object of type LoanApplication. The “mortage” object must have a lenderName (mortgage.getLender) equals to “ACME” and the “application” must have a matching lender name and a creditScore (application.getCreditScore) that is less than 680.
As you can see this rule only gets evaluated if there are two objects of the aforementioned types present and it is only activated if those two objects properties match the conditions in parenthesis.
An observant Java developer will notice that the rule sort of looks like Java code but not quite. The when part list the classes of the objects that must be present and the values of the properties of those instances needed to activate the rule. The when part is purely a pattern matching expression using first order logic. You can think of the when part as the “where” clause in a SQL statement. Just like in a SQL statement you can create aliases for the objects being matches (and their properties). In the “LowCreditScoreRejection” rule we have three aliases “mortgage”, “lender”, “application” and “score”. Once you have aliased a matched object that object can be used somewhere else in the rule condition and also in the rule consequence.
The Rule Consequence
We learned that the rule condition part of the rule determines what pattern of objects that will activate the rule. The “then” part or rule consequence is what happens when the conditions set forth in the “when” part are met. In Drools the consequence is simply a block of Java code. In the “LowCreditScoreRejection” rule example there are two things happening in the “then” part. First we are calling the “reject” method on the application and passing a message telling them why the application is being rejected (notice the use of the alias “score”). Next and last we are creating a new object of type RejectionNotice, passing the application object in the constructor and then passing the newly created object to the insert method. The insert method is a Drools working memory method that tells the rule engine that there is a new object that should be considered when evaluating the rules. In this case the expectation is that there will be another rule that has a condition expecting objects of type RejectionNotice and that will act upon them. The Rule Engine
From the simple example of the “LowCreditScoreRejection” rule we see that a rule engine is a system that matches facts (our data objects) against rules. The rules are then used to infer conclusions about the data. In the example, the conclusions inferred were rejection of the loan application and the creation of the rejection notice. This type of system is what is referred to as a data-driven forward chaining reasoning system. At the heart of the system is an “inference engine”; the component that does the pattern matching, activates the rules and determines how to execute the activated rules. This process is typically referred to as truth maintenance. Under the covers Drools uses a custom version of the popular Rete algorithm (see http://en.wikipedia.org/wiki/Rete_algorithm). As we can see the “forward chaining” process starts with the available facts and uses the rules to infer more facts (such as RejectionNotice) until a desired goal as been reached (determining whether a loan application is approved or rejected and communicating the rejections). Main Drools Classes
The rules like “LowCreditScoreRejection” rule are contained in DRL files (files with the extension .drl) that comply with Drools native rule language syntax. To use the created rules in a Java application you must:
KnowledgeBuilder: A knowledge builder is the class that knows how to load and process DRL files. The impact of parsing and building in memory objects from the DRL file happens at this point. An instance of a knowledge builder can be obtained from the KnowledgeBuilderFactory using the newKnowledgeBuilder() method
KnowledgePackage: A knowledge package is the result of processing a DRL file; a serializable object. The knowledge builder has a getKnowledgePackages() that returns a collection of knowledge packages.
KnowledgeBase: A knowledge base is where the knowledge packages are deployed to so that they can be used at runtime. The knowledge base is the object that will be used to create knowledge sessions. This knowledge base is a thread safe construct that serves as a factory of sessions.
KnowledgeSession: The knowledge session is the object used to interact with the rule engine. It is throught a session that you will make the rule engine aware of the facts (the data) that the rule engine will evaluate against the available rules. Inside the Rule Engine
Inside the rule engine, after you have inserted your facts into a knowledge session and invoked the session fireAllRules() method:
Rules are matched against the facts in the knowledge session using the pattern matcher (Rete algorithm)
The unordered list of activations (the Rules that apply based on the facts) is ordered internally (by a conflict resolver) in the session’s agenda
The first Rule in the agenda is the executed, possibly triggering steps 1 and 2 again
This loop is how a Rule Engine infers knowledge from existing facts using rules. You can see that a Rule Engine using pattern matching to reduce/transform the problem space to arrive at a set of facts that can be considered a solution to the problem at hand. Getting Started with Drools 5: Classifying you Twitter network
Rule Engine development introduces enough conceptual complexity (mainly inherited from the A.I. lingo and academia) that feels fairly unapproachable us Java developers. So, let tackle a simple but yet representative problem using Drools 5.
Read more...

