using drools in your enterprise java application
TRANSCRIPT
![Page 1: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/1.jpg)
Whitepapers, Consulting and Products at
Enterprise Project Rescue
Business Knowledge Management
Development Process
Security, Performance and Architecture
Dynamic Web 2.0 Solutions
©Firstpartners.net 2005. Article may be reproduced in full with this notice.
JBoss Rules in your Enterprise Java application
Author BiographyBased in Dublin, Ireland, Paul Browne has been consulting in Enterprise Java with FirstPartners.net for almost 7 years. When not promoting the Red Piranha (Search and Knowledge Management) and NoUnit (Java Development Process) projects , he can be found blogging online. This article was originally published by O'Reilly books.
These days Enterprise Java could almost send you to sleep. How many hundreds of J2EE-
EJB-Web applications have been written that capture
information from a web page and store it in a database? What
really keeps developers awake at night is trying to write and
maintain the complex business logic in their applications.
This is a problem not only for new applications , but
increasingly for long-lived , business critical , apps whose
internal logic needs to change frequently, often at very short
notice.
In an earlier article Give your business logic a framework with
Drools we introduced the Drools framework and showed how
it could be used to organize complicated business logic. Using
Drools , we were able to replace many , tangled , if...then statements with a simple set of
things we know to be true. If you are ever in a meeting with business customers , and your
head hurts with the complexity of what they want you to implement , then maybe you should
consider a rule engine such as Drools (the JBoss Rules Engine). This article will show you how
you can do this in an Enterprise Java application.
FirstPartners.net email: [email protected] Page 1 of 15
![Page 2: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/2.jpg)
Frameworks all the way down
Most Enterprise Java developers already have their favorite frameworks. In no particular
order , these include presentation frameworks (Struts , JSF , Cocoon , Spring) , persistence
frameworks (JDO , Hibernate , Cayenne and Entity Beans) and structural frameworks (EJB ,
Spring again , Pico and Excalibur), as well as many others. Each framework does one (or
more) very useful thing , and gives developers, a lot of instant 'out-of-the-box' functionality.
Deploying an application using frameworks means you avoid a lot of the boring bits and
concentrate on what is really needed.
Until now , there was a gap in what the frameworks were able to do in that business logic had
no framework. Tools like EJB and Spring are good , but have little to say about how to
organize your if..then statements! Adding Drools to your developer toolbox means that it is
now possible to build an application with 'Frameworks all the way down'. Figure 1 gives a
diagram of such an application.
Figure 1. Frameworks for Java Applications
FirstPartners.net email: [email protected] Page 2 of 15
![Page 3: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/3.jpg)
This article will build on what we already know of the Drools (JBoss Rules) framework and
allow us to build such an application.
When should I use a rule engine?It's almost a cliche in software engineering to say that 'if you have a hammer , everything looks
like a nail'. While rule engines can solve a lot of problems for us , it is worth considering if a
rule engine is appropriate for our Enterprise Java application. Some questions to ask are:
• How complex is my application? For applications that shuffle data to and
from a database , but not much more , it is probably best not to use a rules engine.
However , where there is even a moderate amount of processing implemented in
Java , it is worthwhile considering the use of Drools. This is becuase most
applications develop complexity over time and Drools will let you cope easily with
this.
• What is the lifetime of my application? The answer to this is often
'surprisingly long' - remember the mainframe programmers who thought their
applications wouldn't be around for the year 2000? Using a rule engine pays off
especially in the medium to long term. As this article demonstrates , even
prototypes can benefit from the combination of Drools and agile methods to take
the 'prototype' into production.
• Will my application need to change? The only sure thing about your
requirements is that they will change, either during or just after development.
Drools help you cope with this be specifying the business rule in one or more easy
to configure xml files.
What about performance?If you're writing an Enterprise Application , chances are that it will need to scale to hundreds
if not thousands of users. How will a application using Drools cope with this pressure? The
FirstPartners.net email: [email protected] Page 3 of 15
![Page 4: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/4.jpg)
answer is 'surprisingly well'. While most developers hate to 'lose control' and rely on other
people's code (i.e. a framework) for performance , consider the points below - Drools may
even make your application run faster:
• Avoids Badly written code: Drools guides developers to do 'the right thing'. You
may be sure the code you are writing is good , but would you say the same for your
co-developers? Using a framework makes it easier to write good , fast code.
• Optimized framework: How often have you seen business logic that repeatedly
access a Database for the same information , slowing down the entire application?
Used correctly, Drools can remember not only the information , but also the results
of previous tests using this information, giving the entire application a speed boost.
• Rete Algorithm: Many times we apply 'if'
conditions that we didn't really need. The
Rete Algorithm , as implemented by Drools ,
replaces all the if..then statements with an
optimized network. It is important to note
that the Rete Algorithim involves a tradeoff
between using more memory to reduce delays
at run time. While this isn't a factor in most
modern servers , we wouldn't yet recommend
deploying Drools on your mobile phone!
Where were we ...?In our previous article , we wrote a simple stock trading application based around the Drools
engine. We implemented various business rules , showed how we could rapidly change the
rules to meet changing business requirements and wrote JUnit tests to give us a high degree
of confidence that the system would act as it was supposed to. However , the application as we
left it had little or no user interface , and used hard-coded data instead of a database. To
FirstPartners.net email: [email protected] Page 4 of 15
Whitepapers, Consulting and Products at
Enterprise Project Rescue
Business Knowledge Management
Development Process
Security, Performance and Architecture
Dynamic Web 2.0 Solutions
©Firstpartners.net 2005. Article may be reproduced in full with this notice.
![Page 5: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/5.jpg)
evolve our application into something that is more enterprise level , we need to add two main
things:
• Some sort of User Interface , ideally based one of the standard web-presentation
frameworks.
• A Data Access Object (DAO) to let Drools work with a database (or other back end
system).
Calling the rule engine from a presentation frameworkMost Enterprise Java applications are accessed using a web interface, and one of the most
widely adopted web-presentation frameworks is Struts , from Apache. Ideally , we'll write our
application so that the presentation layer knows about the business layer underneath , but not
the other way around. This has the advantage not only of allowing us to change the
presentation framework at a later date (e.g. to an Ajax or Web Service interface) , but also
means the code examples give should be readily applicable to other web frameworks like
Spring.
Code Snippet 2 demonstrates how you would call the business logic tier (using the rule
engine) from the web presentation layer. The code then uses the results to decide which page
to display. In this sample , we use a Struts action , but the code would be similar for any other
web framework or even a Servlet or JSP Page. This sample still needs a supporting struts-
config.xml , JSP pages to post / display data and a way of generating the war file for
deployment. The aim of this sample is to show how you can integrate the rules engine with the
web framework.
There's a couple of things going on this sample. Often we build up the data we need from the
user over several web pages , so this sample shows how we can achieve this by retrieving the
StockOffer object that we have previously stored in when Web Server session (creating the
FirstPartners.net email: [email protected] Page 5 of 15
![Page 6: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/6.jpg)
object if necessary). Next , we update the StockOffer with any values that the user may have
changed on the web page. We then reset the recommendPurchase flag to clear any previous
results before we call the business logic layer. Finally , we take the response of the business
logic and use it to decide which page to forward the user to.
In this example , note how we split the business logic (yes-no on whether or not to buy a
stock) from the presentation logic (decide which page to go to). This allows us to reuse our
business rules across several different applications In additiona, take look at how the state
information (i.e. things that the user has already told us) is stored in the StockOffer object /
web server session , and not in the Business Layer. By keeping the business layer stateless in
this way, we make the entire application much more scalable and performant.
Code Snippet 2: Integration of Web Presentation layer with Business Logicimport javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import BusinessLayer;/** * Sample Struts action with Pseudocode * to demonstrate how we can call the business * logic (implemented using Drools Rule Engine) * from the web tier. * * For portability , this example gets values from * the HttpServletRequestobject (similar to standard * Servlets) and not the Struts classes. */public class SampleStrutsAction extends Action{ /** * Standard Struts doPerfom method, called * by the struts framework when a matching * request comes in from the browser. */ public ActionForward doPerform( ActionMapping mapping, ActionForm form,
FirstPartners.net email: [email protected] Page 6 of 15
![Page 7: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/7.jpg)
HttpServletRequest request, HttpServletResponse response) throws InvalidEntryPointException { //Local Variables StockOffer userOffer =null; //Get any previous values from the session userOffer=(StockOffer)request.getSession() .getAttribute("PREVIOUS_STOCK_OFFER"); //create this object if it is null if (null==userOffer){ userOffer = new StockOffer(); } //Update with the incoming values //These values match those on the form userOffer.setStockName(request. getParameterValue("STOCK_NAME")); userOffer.setStockPrice(request .getParameterValue("STOCK_PRICE")); userOffer.setStockQuantity(request .getParameterValue("STOCK_QTY")); //Reset the output value userOffer.setRecommendPurchase(null); //Call the Business Layer BusinessLayer .evaluateStockPurchase(userOffer); //Forward to the appropriate page if ("YES".equals( testOffer.getRecommendPurchase()){ return mapping.findForward("YES_WEB_PAGE"); } //otherwise default to the no page return mapping.findForward("NO_WEB_PAGE"); }}
Integrating the rules engine with the Database LayerSo far , our application has a web-presentation layer , a rules engine for the business layer, but
no means of getting data to and from a database. This section gives an example of how to do
this. We base our example on the Data Access Object (Dao) Pattern , where we encapsulate all
code that 'talks' to the database (or back end data source) in one pluggable , configurable
class. As such , the example is applicable to other persistence frameworks such as Hibernate
and Cayenne.
FirstPartners.net email: [email protected] Page 7 of 15
![Page 8: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/8.jpg)
Whitepapers, Consulting and Products at
Enterprise Project Rescue
Business Knowledge Management
Development Process
Security, Performance and Architecture
Dynamic Web 2.0 Solutions
©Firstpartners.net 2005. Article may be reproduced in full with this notice.
Some important points about the way we want to organize the data layer are:
• Only the business layer should talk to the data layer ; if a class in the presentation
layer (front end) wants some data , it should pass through the business layer first.
This helps makes our code easier to organise and read.
• As far as possible , we should keep our data layer stateless – we should hold client
data elsewhere (e.g. In the Server Session at the web front end , as per the previous
example). This is distinct from caching of data , which we can do at this level. The
difference between the two is State information is often user specific , while data we
cache at the Data access layer is mainly sharable across the application. Organizing
our layer in this way increases performance.
• We should allow the business logic to decide if data is needed or not – if not needed
, the call to get the data should not be made.
To implement our simple Data Access Object , we create three
new objects: StockNameDao , DaoImplementation and
DaoFactory.
StockNameDao is an interface that defines two methods :
getStockNames() (returns a list of the stock names that we
deal with) and isOnStockList() (checks that a given stock is
on the list of stocks that we deal with). Our business layer will
call these methods as and when it needs the information.
DaoImplementation is an actual implementation of StockNameDao. In this case the values
are hard coded , but we could have queried a database or accessed an information system like
Blomberg via a web service.
FirstPartners.net email: [email protected] Page 8 of 15
![Page 9: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/9.jpg)
DaoFactory is what we use to create an appropriate instance of StockNameDao. The
advantage it has over creating the class directly is that it allows us to configure what Dao
Implementation we use at runtime (frameworks like Spring are especially good at this). One
factory can return many types of Dao's (e.g. StockNameDao, StockPriceDao ,
StockHistoryDao) , which means we can pass in our DaoFactory , and let the individual
rules decide on the data and Dao's that the require.
Listing 1: StockNameDao.java/** * Defines a Data Access Object - a non data * source specific way of obtaining data. */ public interface StockNameDao { /** * Get a list of stock names for the application * @return String[] array of stock names */ public String [] getStockNames(); /** * Check if our stock is on the list * @param stockName * @return */ public boolean isOnStockList(String stockName);}
Listing 2: DaoImplementation.java/** * Concrete Defininition of a Data Access Object */ public class DaoImplementation implements StockNameDao { /** * Constructor with package level access only * to encourage use of factory method * */ DaoImplementation(){} /** * Get a list of stock names for the app. * This is a hard coded sample
FirstPartners.net email: [email protected] Page 9 of 15
![Page 10: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/10.jpg)
* normally we would get this from * a database or other datasource. * @return String[] array of stock names */ public String[] getStockNames() { String[] stockNames= {"XYZ","ABC","MEGACORP","SOMEOTHERCOMPANY"}; return stockNames; } /** * Check if our stock is on the list * @param stockName * @return true / false as appropriate */ public boolean isOnStockList(String stockName){ //Get our list of stocks String stockList[] = getStockNames(); //Loop and see if our stock is on it // done this way for clarity . not speed! for (int a=0; a<stockList.length;a++){ if(stockList[a].equals(stockName)){ return true; } } //Default returh value return false; }}
Listing 3: DaoFactory.javapackage net.firstpartners.rp;/** * Factory Method to get the Data Access Object. * Normally we could replace this with a * framework like Spring or Hibernate */public class DaoFactory { /** * Get the stock name Dao * This sample is hardcded - in reality * we would makethis configurable / cache * instances of the Dao as appropriate * @return an instance of StockNameDao */ public static StockNameDao getStockDao(){
FirstPartners.net email: [email protected] Page 10 of 15
![Page 11: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/11.jpg)
return new DaoImplementation(); }}
Now that we have our simple Dao implementation to server as our database layer , how do we
integrate it with the drools business layer? Listing 4 , the updated business rules file shows us
how.
Listing 4: BusinessLayer.java (Updated)<?xml version="1.0"?><rule-set name="BusinessRulesSample" xmlns="http://drools.org/rules" xmlns:java="http://drools.org/semantics/java" xmlns:xs=" http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation=" http://drools.org/rules rules.xsd http://drools.org/semantics/java java.xsd"> <!-- Import the Java Objects that we refer to in our rules --> <java:import> java.lang.Object </java:import> <java:import> java.lang.String </java:import> <java:import> net.firstpartners.rp.StockOffer </java:import> <java:import> net.firstpartners.rp.DaoFactory </java:import> <java:import> net.firstpartners.rp.StockNameDao </java:import> <!-- Application Data not associated --> <!-- with any particular rule --> <!-- In this case it's our factory --> <!-- object which gives us back --> <!-- a handle to whatever Dao (Data --> <!-- access object) that we need --> <application-data identifier="daoFactory">DaoFactory </application-data> <!-- A Java (Utility) function --> <! we reference in our rules --> <java:functions>
FirstPartners.net email: [email protected] Page 11 of 15
![Page 12: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/12.jpg)
Whitepapers, Consulting and Products at
Enterprise Project Rescue
Business Knowledge Management
Development Process
Security, Performance and Architecture
Dynamic Web 2.0 Solutions
©Firstpartners.net 2005. Article may be reproduced in full with this notice.
public void printStock( net.firstpartners.rp.StockOffer stock) { System.out.println( "Name:"+stock.getStockName() +" Price: "+stock.getStockPrice() +" BUY:"+stock.getRecommendPurchase()); } </java:functions> <!-- Check for XYZ Corp--> <rule name="XYZCorp" salience="-1"> <!-- Parameters we can pass into--> <!-- the business rule --> <parameter identifier="stockOffer"> <class>StockOffer</class> </parameter"> <!-- Conditions that must be met for --> <!-- business rule to fire --> <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> <!-- Ensure that negative prices --> <!-- are not accepted --> <rule name="Stock Price Not Negative"> <!-- Parameters we can pass into the --> <!-- business rule --> <parameter identifier="stockOffer"> <class>StockOffer</class> </parameter> <!-- Conditions for rule to fire --> <java:condition> stockOffer.getStockPrice() < 0 </java:condition> <!--When rule is activated then ... --> <java:consequence> stockOffer.setRecommendPurchase
FirstPartners.net email: [email protected] Page 12 of 15
![Page 13: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/13.jpg)
(StockOffer.NO); printStock(stockOffer); </java:consequence> </rule> <!-- Check for Negative Prices--> <rule name="Stock Price Low Enough"> <!-- Parameters for the rule --> <parameter identifier="stockOffer"> <class>StockOffer</class> </parameter> <!-- Now uses Dao to get stock list --> <java:condition> daoFactory.getStockDao().isOnStockList( stockOffer.getStockName()) </java:condition> <java:condition> stockOffer.getRecommendPurchase() == null </java:condition> <java:condition> stockOffer.getStockPrice() < 100 </java:condition> <!-- When rule is activated do this --> <java:consequence> stockOffer.setRecommendPurchase( StockOffer.YES); printStock(stockOffer); </java:consequence> </rule></rule-set>
There are several changes to this file to integrate the Data Access Layer with our business
rules:
• At the top of the file , we have several new <java:import> statements to reference
the StockNameDao , DaoImplementation and DaoFactory classes that we
added to the system.
• We have a new tag <application-data> which assigns an instance of the
DaoFactory class to a variable. <application-data> tags are similar to parameters,
except they apply to all business rules , and not just one.
• The 'Stock Price Low Enough' has a new condition , which uses the DaoFactory and StockNameDao to check if the stock is on the list of those that we deal with.
FirstPartners.net email: [email protected] Page 13 of 15
![Page 14: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/14.jpg)
We run our BusinessRulesTest (simulator) again. The simulator / unit tests run ok as
even through we have changed the structure of the program , we haven't (yet) changed what it
does. From looking at the output logs , we can see that our business rules are using
StockNameDao as part of it's evaluations , and that
DaoImplementation.isOnStockList() is being called.
While this example shows the reading of information from a data source, the principles are
the same for writing information , if that is what a rule decided what should be done. The
difference would be our Dao would have a setSomeInformation() method ,and the
method would be called in the <java:consequence> part of the business rule , once the specific
conditions had been met.
Summary and ResourcesIn this article we showed that most Java Server Applications have 3 tiers : Presentation ,
Business logic and Data persistence. While the use of frameworks is widely accepted in the
presentation and persistence layers , until now no framework has been available to
encapsulate low-level business logic. As we've seen in the examples, Drools and JSR-94 are
ideal candidates for reducing the complexity and speeding the development of Java
applications. I hope that these examples inspire you to take a closer look at rule engines , and
that it saves many hours of development and maintence time in your applications.
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 web site
FirstPartners.net email: [email protected] Page 14 of 15
![Page 15: Using Drools in Your Enterprise Java Application](https://reader036.vdocuments.us/reader036/viewer/2022080209/54800897b37959532b8b5a1a/html5/thumbnails/15.jpg)
• Spring Framework web site
• Hibernate Website
• Junit ,Test Framework
• Jess Java Rule Engine
• Jena Semantic and Rule Engine
• JSR-94 Homepage
• Jess in Action Homepage
• Business Rule Thinking (Jess Based)
• General introduction to Rule Systems
FirstPartners.net email: [email protected] Page 15 of 15