Business process automation made easy with Java, Part 2

Design options for rule engine integration

The key benefits of abstracting a rule engine tier from the business object layer are: independent rules maintenance by business users, rules reuse across business objects, and reuse across multiple business contexts by multiple systems. This abstraction is a two-step process that involves:

  • Integrating the external engine with a business tier
  • Selecting the appropriate deployment method and communication protocols between them

In Part 1, we looked at the first step. In this article, we study the second step. We present different methods for rule engine deployment (e.g., stateful versus stateless) and determine the best options for specific situations. In Part 1, we introduced the Java Rule Engine API (Java Specification Request (JSR) 94) that provides a uniform mechanism to access rule engine services. Now we present emerging data interchange standards such as the Simple Rule Markup Language (SRML) that allow vendor independence in rules development.

Read the whole series, "Business Process Automation Made Easy with Java:"

Rule engine integration design options

In this section, we discuss two main options to integrate a rule engine product with a Model-View-Controller (MVC)-based J2EE (Java 2 Platform, Enterprise Edition) Web application. The integration options are based on the engine's invocation mechanism—synchronous or asynchronous. The view's main requirement is synchronization with the model so that data displayed to the user is up to date. Based on the Observer pattern, the model acts as the subject, and the view acts as the observer. Synchronization can be achieved by using a push mechanism, where the view listens for change notification in the model, or a pull mechanism, where the view calls the model to get updated data whenever required, as in a Struts framework.

Figure 1 shows the proposed design for the two integration options. The integration tier is abstracted in this figure to the rule engine controller, and the adapter as explained in Part 1. The pattern's main advantage is loose coupling between the application modules and the rule engine technology used in the back end.

Figure 1. Rule engine integration architecture. Click on thumbnail to view full-size image.

Synchronous invocations

As explained earlier, using the suggested MVC design implies synchronous event execution from the Web tier. As shown in Figure 1, the EJBAction component implements the business logic that may or may not require rules execution. Therefore, in case the need for rules execution arises, EJBAction invokes the RulesController for that purpose. As a result of invoking the RulesController, a rule session object is created and initialized with the required objects (facts) from the model that are needed by the rules set to execute. The initialization objects are obtained by calling the corresponding EJBs (business components) and usually represent a snapshot of the data each EJB represents at the time of invocation. The session object is sent to the rules adapter that abstracts the proprietary Java Rule Engine API from the controller implementation. The adapter extracts the facts from the session, initializes the rule engine with them, then loads the requested rules set from a cache (compiled rules set), and fires the rules.

As a result of firing rules, more facts may be created, and some facts may be altered. The adapter extracts the resulting facts from the rule engine's working memory and puts them back into the session object. The session object returns to the RulesController. The RulesController extracts the facts from the session as a result of rules execution, and then attempts to either update the model components (EJBs) with the altered facts or sends the results back to the Web tier so they can display on the screen as a side effect of rules execution. The decision is based solely on the nature of rules and the application's business logic. For example, server-side validation rules cause the controller to return the results of rules execution as a validation message to the Web tier; meanwhile, action-based rules may cause the controller to update the data in one or more EJBs.

Asynchronous invocations

Some applications require rule engine invocation in asynchronous mode. As shown in the previous section, given the events cycle explained in MVC, asynchronous behavior is not achieved with that design. Messaging middleware, such as Java Message Service (JMS), is recommended for asynchronous rule engine invocation. As shown in Figure 1, the gray components allow the application to communicate asynchronously with the rule engine.

Two JMS queues (or one queue and one topic) can be used as rule engine input queue and rule engine output queue, respectively. The EJBAction detects the need to invoke the rule engine service in an asynchronous fashion and consequently invokes the RequestSender component to accomplish that task. The RequestSender maps the data sent by the EJBAction (mostly optional fact objects and a hint about the rule set to be executed) into an XML message that represents the request to the rule engine. The RequestSender can use a protocol repository to create the XML message; it then puts the message on the rule engine input queue.

A message bean (RulesMBean) listens to the request on the input queue and gets triggered when a request arrives. The RulesMBean extracts the optional facts and the mandatory rules set (or business rule name), and, based on this information, decides which method to call in the rule engine controller. The controller invokes the adapter as mentioned previously and updates the model as a result of firing rules. The controller might decide to send back a response to the message originator; in that case, it would create a response XML message using the ResponseSender component. The ResponseSender puts a message on the rule engine output queue or topic. The ApplicationMBean that listens on the output queue can pick up the response message. The following code snippets illustrate this idea:

...
public class RulesEngineRequest
{
      private Document request;
      private String rulesetName;
      private HashMap properties;
      private String id;
      private String replyTo;
    
      public RulesEngineRequest(String xmlString) throws RulesEngineException
      {
            try
            {
                  request=DocumentBuilder.createDocument();
                  ...
                  ...
                  request.parse(xmlString);
                  rulesetName=null;
                  properties=null;
                  id=null;
                  replyTo=null;
            } catch (Exception ex)
            {
            throw new RulesEngineException("Could not parse the request due to the following exception:\n"+ex);
            }
      }
...
...
public class RulesEngineResponse
{
      private Document response;
      public RulesEngineResponse(IDocument doc) throws RulesEngineException
      {
            response=doc;
            try
            {
                  response.addElement("/rules-response", "result-descriptor");
                  response.addElement("/rules-response/result-descriptor", "outcomes");
            } catch(Exception ex)
            {
              throw new RulesEngineException("Could not create RulesEngineResponse due to the following exception:\n"+ex);
            }
      }
...

... public class RulesMBean implements MessageDrivenBean, MessageListener { ... public void onMessage(Message msg) { TextMessage tm = (TextMessage) msg; try { String text = tm.getText(); RulesEngineRequest request=new RulesEngineRequest(text); String rulesetName=request.getRulesetName(); Map properties=request.getProperties(); ... RulesEngineControllerLocal rulesEngineController=CoreEJBUtil.getRulesEngineControllerLocalHome().create(new HashMap()); rulesEngineController.addFacts(factsList); rulesEngineController.fireRules(rulesetName); factsList=rulesEngineController.getFacts(); ...

Note: Download the complete source code that accompanies this article.

Applying the options

Clearly, business requirements mostly drive invocation method selection; but, from a performance perspective, asynchronous invocation can be more desirable because backend resources can serve it better, and the client can do other tasks during processing. In a credit card authorization scenario, for example, asynchronous invocation might not be an option, but it might be an option for risk underwriting situations. However, the RulesController has no knowledge about the invocation method, and therefore, the same rule set may be fired in two different ways depending on the scenario.

Design considerations

In this section, we discuss some design considerations regarding the suggested integration design.

Data synchronization

One major performance issue with the suggested integration design is the need to synchronize data back to the model components after a rules engine invocation. In a J2EE-distributed environment, the model components can deploy in more than one application server and usually on different JVMs. There is no guarantee that the update process for model components (explained earlier) is done locally, but it usually happens over the network using RMI-IIOP (Remote Method Invocation-Internet Inter-ORB Protocol). Two main approaches overcome this problem:

The first option is to collocate the business components most affected by the rule engine rules-firing on the same JVM as the rule engine. The use of EJB 2.0 local interfaces is most efficient for that purpose. The other approach is to optimize the update cycle by designing the fact objects to implement a Dirty Marker pattern that allows the controller to figure out which object has been altered by the rule engine and which has not. The controller inspects the dirty indicator in all the objects and sends the dirty ones to the corresponding EJB to be stored. It is also worth noting that some rule engine products can deal with EJBs directly as facts in the working memory and might consequently help reduce synchronization overhead. In that case, network overhead of setting and getting granular data members rather than the use of bulk updates as suggested by the proposed design has to be considered.

Workflow engine integration

In certain instances, rule engines are used to make complex decisions about business process routing through business rules execution. In situations like that, we recommend abstracting the rules-firing results in decision objects that can be mapped to XML for easy integration with workflow engines. As an example, let's assume that during a credit card application process the application may route to an underwriter for manual decision-making based on certain data in the applicant profile. In this case, a rule engine would invoke based on data input by the applicant. The rules-firing results would be abstracted into decision objects such as Decline, Approve, or Transfer. Within each decision object, some attributes can be stored, attributes that describe the context of the decision, such as the application identifier or the applicant identifier. The decision objects can be prioritized based on a precedence rule that would, for example, merge all decisions into just one file decision (an Approve with Decline is obviously a Decline). Then the decision can be mapped to XML and parsed by the workflow engine to take appropriate workflow action based on it (e.g., route a task to someone's work queue).

Scalability and quality-of-service (QoS) considerations

Scalability is a concern for most J2EE rule engine implementations. One of the main decisions involves whether to deploy the engine on the same JVM as the rest of the application modules or to deploy it as a standalone server. We recommend embedding the engine in stateless session beans to minimize state overhead, particularly during rules execution. The rules context should never transfer to the caller over RMI to avoid serialization overhead.

Other aspects of scalability such as memory utilization per engine instance and CPU utilization, which are vendor/technology dependent, are outside the scope of this article. Always execute an engine deployment-mode performance test in a controlled test environment to avoid surprises.

Given the nature of embedded components, the rule engine can take advantage of QoS options offered by the application server platform that houses it. Most enterprise-grade application servers such as IBM WebSphere or BEA WebLogic offer optimum deployment and configuration options for EJBs in meeting QoS objectives of performance, reliability, availability, and failover. For example, very high scalability can be achieved by deploying a rule engine as a stateless session bean, as stateless beans have minimal creation overhead, and an enterprise-grade server can spawn them quickly. Other QoS options offered by some vendors include session failover whereby a critical decision component can be automatically failed-over to an active replica during server failures. In order to leverage failover, however, the session bean must deploy as stateful. The embedded approach also enables independent scaling of the rule engine platform for optimum performance.

Tying it all together: A sample interaction flow

Now that we have seen the nuts and bolts of rule engine integration with the rest of the business tier, we present an example interaction flow that demonstrates how a rule engine invokes for a risk evaluation scenario. This interaction is assumed to be asynchronous. See Figure 2 below:

Figure 2. Component interaction diagram. Click on thumbnail to view full-size image.
  1. Client requests a risk evaluation by sending a message to the middle tier. The client can be a Web client or any enterprise component.
  2. The EJBController on the middle tier delegates the request to an event handler (EJBAction) to process the request.
  3. The handler recognizes that the request is a rule request and forwards it to the RequestSender, a generic queue publisher for asynchronous rule engine invocations.
  4. The RequestSender creates an XML document from the message that contains the evaluateRisk object and publishes it to a known queue. The control now returns to the client, which may be notified that the request is being processed.
  5. A RulesMBean is activated upon the message, and it forwards the request to the rule integration framework (the controller).
  6. The RulesController packages the request appropriately for the adapter and invokes the Rules Adapter API.
  7. The RulesAdapter abstracts the API of the specific rule engine product. It establishes the appropriate context for the engine and then triggers the rules set to be executed by the engine.
  8. The engine executes the rules and creates a ResponseObject for sending back the results.
  9. The ResponseObject creates a response XML document and publishes to a well-known JMS queue.
  10. An ApplicationMBean is activated, and it manages the response back to the client by interacting with a workflow engine, for example.

Simple Rule Markup Language (SRML)

In Part 1, we briefly covered the emerging Java Rule Engine API (JSR 94). It only addresses part of the problem for enterprises that desire vendor independence and transparency in technology investments. The Java Rule Engine API defines a multistep protocol for invoking a rule engine, adding facts to the engine, triggering rules, and getting results back. It is equivalent to a JDBC (Java Database Connectivity) API for RDBMS (relational database management system) access. In the previous sections, we showed that one way to accomplish the goal of vendor independence is to build a rule engine API adapter such that only the adapter will need to be rewritten should an enterprise change the rule engine product.

A bigger issue is rules development. How can an enterprise share rules developed in multiple products or migrate rules when moving from one vendor product to another? A common rules representation is required to accomplish this, and the SRML is one initiative gaining acceptance and adoption by leading rule engine product vendors such as Ilog. A preliminary document type definition is available, and rules expressed in SRML can be easily translated and executed on any platform supporting it. See Resources for additional references on rule markup languages.

Young, but growing

Business process automation is still in its early stages. While enterprises have been implementing basic automation capabilities, the idea of applying them across the entire value chain is only beginning to develop. Enterprises want to invest in technology solutions based on open standards such as Java and J2EE and demand that their investments are well protected over the long haul.

In this two-part series, we covered the role of rule engines in this evolution and how to integrate them within a J2EE enterprise. We presented a rule engine integration framework, design choices for rules invocation, and best-practice considerations for optimal performance. We also discussed emerging standards such as the Java Rule Engine API and rule markup languages like SRML. The articles are based on our hands-on experience delivering large automation projects. We hope you will benefit from the ideas we have described here and from several excellent references included in Resources below.

Siva Visveswaran, with more than 14 years of IT industry experience, has for the past 3 years designed and implemented large and complex J2EE applications for Fortune 100 financial service companies and dot-coms. Most recently, he has developed business process automation solutions using J2EE for a large financial services company. He currently works as a principal consultant at a large management consulting firm for its IT strategy practice. Siva has a master's degree in computer science from Wayne State University in Detroit, Mich. Ahmed Abulsorour has worked in the IT field for more than 7 years, and for the past 3 years has been designing medium-to-large complexity middleware platforms based on CORBA, COM (Component Object Model), and J2EE for Fortune 500 financial service companies and dot-coms. Abulsorour has most recently worked with Expert Shell, optimization, rule engine, and J2EE technologies in a complex integration platform for a large financial services company. He currently works as a principal consultant for a large management-consulting firm. He has bachelor degrees in computer science and mechanical engineering from the American University in Cairo, Egypt.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more