Give Your Business Logic a Framework with Drools
Pages: 1, 2, 3, 4, 5, 6, 7
Conflict Resolution
Now the folks on the business side are really impressed and are starting to think through the possible options. They've come across a problem with stocks of XYZ Corp and have decided to implement a new rule: Only buy stocks of XYZ Corp if they are less than 10 Euro.
As before, you add the test to our simulator and include the new business rule in our rules file, as per the following listings. First, we add a new method to BusinessRuleTest.java:
/**
* Makes sure the system will buy stocks
* of XYZ corp only if it really cheap
*/
public void testXYZStockBuy() throws Exception{
//Create a Stock with our simulated values
StockOffer testOfferLow = new StockOffer();
StockOffer testOfferHigh = new StockOffer();
testOfferLow.setStockName("XYZ");
testOfferLow.setStockPrice(9);
testOfferLow.setStockQuantity(1000);
testOfferHigh.setStockName("XYZ");
testOfferHigh.setStockPrice(11);
testOfferHigh.setStockQuantity(1000);
//Run the rules on it and test
BusinessLayer.evaluateStockPurchase(
testOfferLow);
assertTrue("YES".equals(
testOfferLow.getRecommendPurchase()));
BusinessLayer.evaluateStockPurchase(
testOfferHigh);
assertTrue("NO".equals(
testOfferHigh.getRecommendPurchase()));
}
Next, we need a new <rule> in
BusinessRules.drl:
<rule name="XYZCorp" salience="-1">
<!-- Parameters we pass to rule -->
<parameter identifier="stockOffer">
<class>StockOffer</class>
</parameter>
<java:condition>
stockOffer.getStockName().equals("XYZ")
</java:condition>
<java:condition>
stockOffer.getRecommendPurchase() == null
</java:condition>
<java:condition>
stockOffer.getStockPrice() > 10
</java:condition>
<!-- What happens when the business
rule is activated -->
<java:consequence>
stockOffer.setRecommendPurchase(
StockOffer.NO);
printStock(stockOffer);
</java:consequence>
</rule>
Note that in the business rules file, after the rule name, we
set our salience to -1 (i.e., the lowest
priority of all of the rules we have specified so far). Most of the
rules in our system conflict, meaning Drools must make some
decision on the order in which to fire rules, given that the
conditions for all of the rules will be met. The default way of
deciding is:
Salience: A value we assign, as per the above listing.Recency: How many times we have used a rule.Complexity: Specific rules with more complicated values fire first.LoadOrder: The order in which rules are loaded.
If we did not specify the saliency of our rule in this example, what would happen is:
- The XYZ Corp rule ("Don't buy XYZ if the price is more than 10
Euro") would fire first (the status of the
Recommend Buyflag would be set toNo). - Then the more general rule ("Buy all stock under 100") fires,
setting the
Recommended Buyflag toyes.
This would give a result that we don't want. However, since our example does set the saliency factor, the test and our business rules work as expected.
While most of the time, writing clear rules and setting the saliency will give enough information to Drools for it to choose the proper order in which to fire rules, sometimes we want to change the entire manner in which rule conflicts are resolved. An example of how to change this is given below, where we tell the rule engine to fire the simplest rules first. A word of warning: be careful when changing conflict resolution, as it can fundamentally change the behavior of the rule engine--a lot of problems can be solved first with clear and well-written rules.
//Generate our list of conflict resolvers
ConflictResolver[] conflictResolvers =
new ConflictResolver[] {
SalienceConflictResolver.getInstance(),
RecencyConflictResolver.getInstance(),
SimplicityConflictResolver.getInstance(),
LoadOrderConflictResolver.getInstance()
};
//Wrap this up into one composite resolver
CompositeConflictResolver resolver =
new CompositeConflictResolver(
conflictResolvers);
//Specify this resolver when we load the rules
businessRules = RuleBaseLoader.loadFromUrl(
BusinessLayer.class.getResource(
BUSINESS_RULE_FILE),resolver);
For our simple application, driven by JUnit tests, we don't need to alter the way the Drools resolves rule conflicts. It is useful to know how conflict resolution works, especially when your application grows to meet more complex and demanding requirements.
Conclusion
This article demonstrated a problem that most programmers have had to face: how to put some order on the complexity of business logic. We demonstrated a simple application using Drools as a solution and introduced the notion of rule-based programming, including how these rules are resolved at runtime. Later on, a follow-up article will take these foundations and show how to use them in an enterprise Java application.
Resources
- Sample code for this article
- Drools Project home page
- Info on Drools rules
- "Introduction to Drools and Rule Engines," by the Drools project lead
- Drools rules schema files
- JSR-94, Java Rule Engines, Overview
- Struts framework website
- Spring framework website
- Hibernate website
- JUnit test framework
- Jess Java rule engine
- Jena semantic and rule engine
- JSR-94 home page
- Jess in Action home page
- "Business Rule Thinking" (Jess-based)
- "General Introduction to Rule Systems"
- "Jess Implementation of the Rete Algorithm"
Paul Browne , based in Dublin, Ireland, has been consulting in enterprise Java with FirstPartners.net for almost seven years.
Return to ONJava.com.
-
Business rules management systems are not business rules engines
2006-06-19 16:01:10 JT_EDM [View]
- Trackback from http://strator.dyndns.org/weblog/index.php?/archives/57-Give-Your-Business-Logic-a-Framework-with-Drools.html
Give Your Business Logic a Framework with Drools
2005-09-25 23:45:24 [View]
- Trackback from http://gleamynode.net/wordpress/archives/74
Drools 소개: Open Source Rule Engine
2005-08-16 00:38:14 [View]
-
Performance Considerations Also
2005-08-08 09:59:45 johnwatts1 [View]
-
rule contexts
2005-08-08 09:00:36 brjado [View]
-
Business Users
2005-08-04 08:01:47 vikdavid [View]
-
is that really any easier?
2005-08-03 18:29:21 prpatel [View]