Using Drools in Your Enterprise Java Application
Pages: 1, 2, 3, 4
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 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 Framework
Most 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.
The following code snippet demonstrates how to call the business logic tier (using the rule engine) from the web presentation layer. The code uses the results to decide which page to display. In this sample, we use a Struts action, but the code is similar for any other web framework or even a servlet or a JSP page. This snippet works with a supporting struts-config.xml, JSP pages to post/display data, and a way of generating the WAR file for deployment. The snippet shows how to integrate the rule engine with the web framework.
import 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
*/
public class SampleStrutsAction extends Action{
/**
* Standard Struts doPerfom method
*/
public ActionForward doPerform(
ActionMapping mapping,
ActionForm form,
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");
}
}
There are 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
the web server session. 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 addition, 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.