We've discussed several times in this book how JBoss ESB enables you to re-use existing code by creating services that "plug" into the ESB instead of having to reinvent the wheel in your applications. JBoss ESB's integrations with other JBoss technologies serve a similar role in that they enable your services to take advantage of the unique capabilities provided by these technologies, without your having to recreate those capabilities in your own code.
What do we mean when we talk about "rules-based" programming?
Rules-based programming involves defining decision points that are controlled by rules. This is similar to other types of programming, but what makes rules-based programming different is that you separate the rules-related decision points from other programming logic. This may sound like a hair-splitting difference, but it's a big deal because:
All of which leads s to JBoss Drools. (http://www.jboss.org/drools)
Drools is sometimes thought of as a rules-based programming language and runtime engine, but it's really more than that. Drools is a unified and fully integrated solution for Business Rules, Business Processes Management, Task Planning, and Event Processing . The JBoss Drools project is organized into sub-projects, each of which handles one technology. The Drools "Expert" sub-project covers the rules-based programming that you can use in the JBoss ESB-Drools integration. The Expert sub-project includes the Rules API, the Rules engine, and Eclipse-based editing and debugging tools.
Now, don't panic! Just because the sub-project's name is "Expert" doesn't mean that you have to be an expert to learn how to program in Drools. What does a Drools rule look like? Let' take a look at a rule.
Rules are written in the Drools Rule Language. The file extension for a Drools rule file is .drl
This language is generic in nature, so that it can handle rules for a large variety of applications. This rules language can also be extended to handle specific types of rules applications such as accounting, medical, and so on. These extensions are referred to as Domain Specific Languages (DSL).
Now, every rule follows a basic form. There's a left-hand side (LHS) and a right-hand side (RHS). The left side defines the
when
clause, in other words the condition that causes the rule to execute. And, the right side defines the then
, in other words, the consequences of the rule being executed. Here's a simple example of a rule:
rule "a simple rule" when (LHS) you need a rules-based app then (RHS) build it with JBossDrools!
Just like any other programming language, in order for a rule to do something useful, it needs access to information to process. How does a rule access information? Through Drools' working memory. The way it works is that information in the form of Java beans is loaded into working memory. Drools refers to these beans as "facts"—since in the real world your memory is full of facts too. Facts are typically packaged and distributed in Java jar files. By using Java beans as facts, Drools is able to access the data elements in facts through the beans' getter and setter methods.
When and if a rule is executed depends on the state of things in working memory. Changes in working memory resulting from facts being inserted into working memory, changing or being updated in working memory, or being removed from working memory, can cause the rules' when
conditions to become true
and the result in one or more rules being executed.
The determination as to when a rule is executed is a major difference between rules-based programming in Drools and procedural programming. How does Drools decide which rule to run first when conditions in working memory satisfy multiple rules' LHS conditions? The Drools rules runtime engine does not decide which rules to run based on a hard-coded sequence of rules. What the rules engine does instead is it adds each rule with a matching condition rule to its "agenda" of rules to run. If the agenda includes more than one rule, then the rules engine has to perform conflict resolution on the rules to decide on the sequence in which the rules should be run. The rules engine performs this conflict resolution based on a combation of factors including:
The JBoss ESB-Drools integration enables you to access rules from your service's actions. There are two JBoss ESB classes that support this:
org.jboss.soa.esb.actions.BusinessRulesProcessor
org.jboss.soa.esb.actions.DroolsRuleService
The BusinessRuleProcessor
(this is sometimes referred to as "BRP") class uses rules loaded from rules files. This works well for relatively simple rules services. But, loading lots of rules from lots of files can be hard to maintain and makes for inefficient processing.
This service uses the RuleAgent
class (org.drools.agent.RuleAgent
) to either access packages of rules from files, or, to handle a more complex environment, where you want to use large numbers of complex rules services, and hundreds or even thousands of rules, DroolsRuleService
is the better choice. In a large scale implementation such as this, you would not keep the rules in a correspondingly large number of standalone files. Instead, you would use a Business Rules Management System (BRMS) such as Drools Guvnor (http://www.jboss.org/drools/drools-guvnor.html).
Guvnor makes it easier to handle a production environment and a large number of rules (and large numbers of people writing rules) by implementing a central repository (backed by a database) for rules, with a web-based rules authoring interface that provides import/export/archiving functions, audit trails for changes made to rules, an error log to help debug problems, automated test development and execution, rule status tracking, and version control. Guvnor makes it easier for business rules expert non-programmers to create rules and for administrators to maintain large numbers of rules and manage multiple users.
Here's what Guvnor looks like:
JBoss ESB supports rules services that are either stateless or stateful. In the stateless model, messages sent to the services contain all the facts to be inserted into the rules engine's working memory, before the rules are executed. In the stateful model, where the execution of the rules may take place in a session over an extended time period, several messages may be sent to a rule service, and the rules may fire and update either the message or the facts until a final message causes the service to end the session.
To see the JBoss ESB-Drools integration in action, take a look at any of the quickstarts whose names begin with "business_ruleservice" or review the JBoss ESB-Drools integration in the JBoss ESB Programmers' guide:
http://docs.jboss.org/jbossesb/docs/4.10/manuals/html/Programmers_Guide/index.html
In the business_rules_service
JBoss ESB quickstart, a business order placement system is simulated. Part of this system assigns a sales discount percentage to incoming customer orders, customer status (gold, platinum, and so on) and order priority.
The action that invokes the rules processor looks like this:
<action class="org.jboss.soa.esb.actions.BusinessRulesProcessor" name="BRP"> <property name="ruleSet" value="MyBusinessRules.drl" /> <property name="ruleReload" value="true" /> <property name="object-paths"> <object-path esb="body.orderHeader" /> <object-path esb="body.customer" /> </property> </action>
Here's a fragment of the rules file (MyBusinessRules.drl
) that is referenced in the action. Note that the salience
value of the logging rule is lower than that of the customer order processing rules (as order processing is more time critical than logging). Also note how using Drools enables you to move the business process rules definitions out of your application programs and into a separate rules file.
The syntax of the rules follow the when/then model we discussed previously. The net result of the execution of these rules is to define the appropriate customer discount based on the customer status and order priority included in the messages processed by the ESB services.
rule "Logging" salience 10 when order: OrderHeader() customer: Customer() then System.out.println("Customer Status: " + customer.getStatus()); System.out.println("Order Total: " + order.getTotalAmount()); end rule "Customer Platinum Status" salience 20 when customer: Customer(status > 50) order: OrderHeader(orderPriority == 3) then System.out.println("Platinum Customer - High Priority -Higher discount"); order.setOrderDiscount(8.5); end rule "Customer Gold Status" salience 20 when customer: Customer(status > 10, status <= 50) order: OrderHeader(orderPriority == 2) then System.out.println("Gold Customer - Medium Priority - discount "); order.setOrderDiscount(3.4); end
JBoss ESB's support for web services is described in detail in Chapter 8. This support is augmented by the JBoss ESB integration with the JBoss' open source BPEL engine, RiftSaw (http://www.jboss.org/riftsaw). RiftSaw enables you to integrate BPEL processes (which are exposed as web services).
There are a couple of set-up tasks that you have to perform before you can use Riftsaw with JBoss ESB, they are:
Let's install RiftSaw first. To do this, follow these steps: the entire set-up process is documented in the RiftSaw Getting Started Guide (http://docs.jboss.org/riftsaw/releases/2.3.0.Final/gettingstartedguide/html/)—we're covering the steps that will work for the JBoss AS server and JBoss ESB installation used throughout the book.
cd /opt/local; mkdir riftsaw ; cd riftsaw
http://downloads.jboss.org/riftsaw/releases/2.3.0.Final/riftsaw-2.3.0.Final-src.zip
unzip riftsaw-2.3.0.Final-src.zip
cd /opt/local/riftsaw-2.0-SNAPSHOT/install
mvn clean install -P docs
deployment.properties
file and set org.jboss.esb.server.home=/opt/local/jboss-5.1.0.GA
and org.jboss.esb.home=/opt/local/jbossesb-4.10
.ant deploy
/jboss/local/riftsaw/riftsaw-2.3.0.Final/samples/
Next, you shold install the BPEL Process Editor into JBDS.
Strictly speaking, installing the BPEL editor is an optional step, but it's a tool that will make your life a lot easier (Easier than trying to create and maintain BPEL process definitions by editing raw XML, that is). The tool is a visual editor for BPEL processes. It's not installed into the default JBDS download, but it's easy (and of course, it's also free) to install it. The installation steps are as follows:
Note that the JBoss ESB-RiftSaw integration is similar to the JBoss ESB-JBPM integration (explained in a different section of this appendix), with one important difference. When we're dealing with BPEL, which means dealing with web services, all communication is synchronous and follows a request-response pattern. This makes the RiftSaw-JBoss ESB integration simpler than the corresponding JBPM-JBoss ESB integration in that just one message exchange pattern (MEP) is supported. The JBoss ESB-RiftSaw integration supports two types of operations:
Orchestration with RiftSaw is actually very simple as from the ESB's point of view, the BPEL process is just another web service. This means that the ESB is able to receive messages from a RiftSaw BPEL process just as it would from any other web service.
org.jboss.soa.esb.actions.bpel.BPELInvoke
OOTB action can be used if RiftSaw is running in the same Java VM as the JBoss ESB and if the BPEL process to be invoked is also deployed to the local RiftSaw instance. In addition, the BPELInvoke
action lets you specify not just the RiftSaw process to be invoked, but also the specific operation that you want to execute within that process.In the esb_helloworld
quickstart, the following action invokes the BPEL process: Remember, that as far as the ESB is concerned, the BPEL process is just another web service that is accessed through its WSDL.
<action name="action2" class="org.jboss.soa.esb.actions.bpel.BPELInvoke"> <property name="service" value="{http://www.jboss.org/bpel/examples/wsdl}HelloService"/> <property name="operation" value="hello" /> <property name="requestPartName" value="TestPart" /> <property name="responsePartName" value="TestPart" /> </action>
And, here's the corresponding service definition in the WSDL:
<wsdl:service name="HelloService"> <wsdl:port name="HelloPort" binding="tns:HelloSoapBinding"> <soap:address location="http://localhost:8080/Quickstart_bpel_hello_worldWS"/> </wsdl:port> </wsdl:service>
Just as "middleware" can be a confusing term, "Business Process Management (BPM)" can also be an overused and misunderstood term. What it really comes down to is a systematic approach to defining, reviewing, and ultimately making business processes more effective. One of JBoss ESB's most powerful integrations is with JBoss jBPM. This integration enables you to connect your business processes to ESB services.
Before we describe this integration, how it works, and how you can use it, we have to be certain that we understand the definition of a "business process". In the context of Business Process Management, a process is not an active, executing program or application. We're talking about the process by which your business performs operations to fulfill a business requirement. For example, a business process can define the tasks that a business performs to execute a retail sale, request that a credit account be opened, restock a supply warehouse, or send bills to customers. The means that your business uses to perform these tasks can be manual, mechanical, involve software, or be a combination of all these approaches.
jBPM is the JBoss open source BPM framework. jBPM provides an Eclipse-based development environment, an administrative console, and a workflow management system. In jBPM, processes are defined in a Java-like Process Definition Language (jPDL). The jBPM development also includes a Graphical Process Design tool (GPD) that enables you to design your processes visually. Note that the process has a start and an end, references to multiple services, and transitions between states, based on the results of operations, including conditional operations.
Finally, since a business process can be "long-running", where humans and computers often have to wait for something to happen (such as waiting for a credit application to be approved), jBPM includes a process engine runtime (this must be deployed to an application server) that is able to maintain a process state (in a database) while it runs and wais.
The JBoss ESB-jBPM integration supports two types of operations:
Orchestration enables a jBPM process to combine with JBoss ESB services, but maintain control over the combination of services and the process.
To see the JBoss ESB-jBPM integration in action, take a look at any of the quickstarts whose names begin with "bpm" or review the JBoss ESB-jBPM integration in the JBoss ESB Programmers' guide:
http://docs.jboss.org/jbossesb/docs/4.10/manuals/html/Programmers_Guide/index.html
Calling a jBPM process from a JBoss ESB service uses the org.jboss.soa.esb.services.jbpm.actions.BpmProcessor
action. Under the covers, this action uses the jBPM command API to execute three possible operations:
NewProcessInstanceCommand
: This creates a new ProcessInstance
using a process definition that has already been deployed to jBPM. The process instance is left in the start state so that tasks referenced by the start node are executed.StartProcessInstanceCommand
: This is the same as NewProcessInstanceCommand
, except that the process instance that is created is moved from the start position to the first node in the process graph.CancelProcessInstanceCommand
: This cancels a process instance.All of these operations require ESB action
attributes such as a process ID to be defined. The action
definitions that call the jBPM process can also specify additional information in action configuration properties. For example, the esbToBpmVars
property defines the variables that are to be extracted from the message from the ESB and set in the jBPM context.
In the bpm_orchestration2
JBoss ESB quickstart, a jBPM process is used to simulate a sales order processing system. The following action is used to start a new jBPM process (after that process has been previously deployed), to pass the process variables, and to map these variables from information extracted from the messages the JBoss ESB service processes to the jBPM process variables:
<action name="start_a_new_process_instance" class="org.jboss.soa.esb.services.jbpm.actions.BpmProcessor"> <property name="command" value="StartProcessInstanceCommand" /> <property name="process-definition-name" value="bpm_orchestration2Process"/> <property name="esbToBpmVars"> <mapping esb="eVar1" bpm="counter" value="45" /> <mapping esb="BODY_CONTENT" bpm="theBody" /> </property> </action>