using drools in your enterprise java application

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. JBoss Rules in your Enterprise Java application Author Biography Based 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

Upload: paulbrowne

Post on 29-Nov-2014

134 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Using Drools in Your Enterprise Java Application

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

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

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

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

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

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

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

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

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

* 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

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

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

(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

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

• 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