JBoss.orgCommunity Documentation

Services Guide

Your guide to services available in JBossESB

Logo

Abstract

This book contains details of the services available within the JBossESB.


1. The Registry
1.1. What is the Registry?
1.1.1. Introduction
1.1.2. Why do I need it?
1.1.3. How do I use it?
1.1.4. Registry Vs Repository
1.1.5. SOA components
1.1.6. UDDI
1.1.7. The Registry and JBossESB
1.2. Configuring the Registry
1.2.1. The Components Involved
1.2.2. The Registry Implementation Class
1.2.3. Using JAXR
1.2.4. Using jUDDI Transports
1.2.5. Using Scout and jUDDI
1.2.6. Registry Interceptors
1.3. Registry Configuration Examples
1.3.1. Embedding
1.3.2. RMI using the jbossesb.sar
1.3.3. RMI using your own JNDI Registration of the RMI Service
1.3.4. SOAP
1.4. Registry Troubleshooting
1.4.1. Scout and jUDDI pitfalls
1.4.2. More Information
2. Rule Services
2.1. What is a Rule Service?
2.1.1. Introduction
2.2. Rule Services using Drools
2.2.1. Introduction
2.2.2. Rule Set Creation
2.2.3. Rule Service Consumers
2.2.4. Configuration
2.2.5. Object Paths
2.2.6. Channels
2.2.7. Deploying and Packaging
3. Content-Based Routing
3.1. What is Content-Based Routing?
3.1.1. Introduction
3.1.2. Simple example
3.2. Content-Based Routing using XPath
3.2.1. Introduction
3.2.2. Inline Rule Definitions
3.2.3. External Rule Definitions
3.2.4. Namespaces
3.3. Content-Based Routing using Regex
3.3.1. Introduction
3.3.2. Inline Rule Definitions
3.3.3. External Rule Definitions
3.4. Content-Based Routing Using Drools
3.4.1. Introduction
3.4.2. Three Different Routing Action Classes
3.4.3. Rule-Set Creation
3.4.4. XPath Domain Specific Language
3.5. Content-Based Routing Using Smooks
3.5.1. Introduction
4. Message Transformation
4.1. Overview
4.2. Smooks
4.2.1. Samples and Tutorials
4.3. XSL Transformations
5. jBPM 3 Integration
5.1. Introduction
5.2. Integration Configuration
5.3. jBPM configuration
5.4. Creation and Deployment of a Process Definition
5.5. JBossESB to jBPM
5.5.1. Exception Handling JBossESB to jBPM
5.6. jBPM to JBossESB
5.6.1. EsbNotifier
5.6.2. EsbActionHandler
5.6.3. Exception Handling jBPM -> JBossESB
5.6.4. Scenerio One: Time-out
5.6.5. Scenario Two: Exception Transition
5.6.6. Scenario Three: Exception Decision
6. jBPM 5 Integration
6.1. Integration Configuration
6.2. jBPM 5 configuration
6.3. Creation and Deployment of a Process Definition
6.4. JBossESB to jBPM
7. Service Orchestration
7.1. Introduction
7.2. Orchestrating Web Services
7.3. Orchestration Diagram
7.4. Process Deployment and Instantiation
7.5. Conclusion
8. The Message Store
8.1. Introduction
8.2. Message Store Interface
8.2.1. Transaction
8.3. Configuring the Message Store
9. Security
9.1. Introduction
9.2. Security Service Configuration
9.2.1. Configuring Security on Services
9.3. Authentication
9.3.1. Authentication Request
9.4. JBossESB SecurityContext
9.5. Security Context Propagation
9.6. Customising security
9.7. Provided Login Modules
9.7.1. CertificateLoginModule
9.7.2. Role Mapping
9.8. Password Encryption
9.8.1. Creating an Encrypted Password File
9.8.2. SecurityService
10. References
A. Revision History

As the W3C puts it: An SOA is a specific type of distributed system in which the agents are "services": http://www.w3.org/TR/2003/WD-ws-arch-20030808/#id2617708.

The key components of a Service Oriented Architecture are the messages that are exchanged, agents that act as service requesters and service providers, and shared transport mechanisms that allow the flow of messages. A description of a service that exists within an SOA is essentially just a description of the message exchange patter between itself and its users. Within an SOA there are thus three critical roles: requester, provider, and broker.

Service Provider

allows access to services, creates a description of a service and publishes it to the service broker.

Service Broker

hosts a registry of service descriptions. It is responsible for linking a requestor to a service provider.

Service Requester

is responsible for discovering a service by searching through the service descriptions given by the service broker. A requestor is also responsible for binding to services provided by the service provider.

The JBossESB Registry architecture allows for many ways to configure the ESB to use either a Registry or Repository. By default we use a JAXR implementation (Scout) and a UDDI (jUDDI), in an embedded way.

The following properties can be used to configure the JBossESB Registry. In the jbossesb-properties.xml there is section called 'registry':


<properties name="registry">
  <property name="org.jboss.soa.esb.registry.implementationClass"
    value="org.jboss.internal.soa.esb.services.registry.JAXRRegistryImpl"/>
  
  <property name="org.jboss.soa.esb.registry.factoryClass"
    value="org.apache.ws.scout.registry.ConnectionFactoryImpl"/>
  
  <property name="org.jboss.soa.esb.registry.queryManagerURI"
    value="org.apache.juddi.v3.client.transport.wrapper.UDDIInquiryService#inquire"/>
  
  <property name="org.jboss.soa.esb.registry.lifeCycleManagerURI"
    value="org.apache.juddi.v3.client.transport.wrapper.UDDIPublicationService#publish"/>
  <property name="org.jboss.soa.esb.registry.securityManagerURI"
    value="org.apache.juddi.v3.client.transport.wrapper.UDDISecurityService#secure"/>
  
  <property name="org.jboss.soa.esb.registry.user" value="root"/>
  <property name="org.jboss.soa.esb.registry.password"  value="root"/>
  
  <property name="org.jboss.soa.esb.scout.proxy.uddiVersion" value="3.0"/>
  <property name="org.jboss.soa.esb.scout.proxy.uddiNameSpace" value="urn:uddi-org:api_v3"/>
  
  <property name="org.jboss.soa.esb.scout.proxy.transportClass"
    value="org.apache.ws.scout.transport.LocalTransport"/>
  <!-- specify the interceptors, in order -->
  <property name="org.jboss.soa.esb.registry.interceptors"
  value="org.jboss.internal.soa.esb.services.registry.InVMRegistryInterceptor, org.jboss.internal.soa.esb.services.registry.CachingRegistryInterceptor"/>
  <!-- The following properties modify the cache interceptor behaviour -->
  <property name="org.jboss.soa.esb.registry.cache.maxSize" value="100"/>
  <property name="org.jboss.soa.esb.registry.cache.validityPeriod" value="600000"/>
  
  <!-- Organization Category to be used by this deployment. -->
  <property name="org.jboss.soa.esb.registry.orgCategory"         
  value="org.jboss.soa.esb.:category"/>
</properties>

Table 1.1. Registry Properties

PropertyDescription
org.jboss.soa.esb.registry.implementationClass

A class that implements the jbossesb Registry interface. We have provided one implementation (JAXRRegistry interface).

org.jboss.soa.esb.registry.factoryClass

The class name of the JAXR ConnectionFactory implementation.

org.jboss.soa.esb.registry.queryManagerURI

The URI used by JAXR to query

org.jboss.soa.esb.registry.lifeCycleManagerURI

The URI used by JAXR to edit.

org.jboss.soa.esb.registry.securityManagerURI

The URI used to authenticate.

org.jboss.soa.esb.registry.user

The user used for edits.

org.jboss.soa.esb.registry.password

The password to go along with the user.

org.jboss.soa.esb.scout.proxy.uddiVersion

The UDDI version of the query.

org.jboss.soa.esb.scout.proxy.uddiNameSpace

The UDDI namespace.

org.jboss.soa.esb.scout.proxy.transportClass

The name of the class used by scout to do the transport from scout to the UDDI.

org.jboss.soa.esb.registry.interceptors

The list of interceptors that are applied to the configured registry. The codebase currently provides two interceptors, one for handling InVM registration and a second for applying a cache over the registry.

The default interceptor list consists solely the InVM interceptor.

org.jboss.soa.esb.registry.cache.maxSize

The maximum number of server entries allowed in the cache. If this value is exceeded then entries will be evicted on a LRU basis. The default value is 100 entries.

org.jboss.soa.esb.registry.cache.validityPeriod

The validity period of the caching interceptor. This is specified in milliseconds and defaults to 600000 (ten minutes). If this value is zero (or less) then there is no expiry specified on the cache.

org.jboss.soa.esb.registry.orgCategory

The Organization Category name for the ESB instance. Default is "org.jboss.soa.esb.:category".


Property: org.jboss.soa.esb.scout.proxy.transportClass

When using Scout with a UDDI implementation there is an additional parameter that one can set - the transport class that is used for communication between Scout and the UDDI registry. If you are using Scout to communicate with jUDDI v3, we suggest leaving the transportClass as LocalTransport and using jUDDI's esb.juddi.client.xml to use jUDDI's transports (InVM, RMI, WS).

jUDDI's esb.juddi.client.xml resides in the server/<config>/deploy/jbossesb.sar/META-INF directory and contain the concept of a “node”, which is a jUDDI registry location. Use the node settings to determine whether you want to use JAX-WS, InVM, or RMI as your transport:


<node>
        <!-- required 'default' node -->
        <name>default</name> 
        <description>Main jUDDI node</description>
        <properties>
    <property name="serverName" value="localhost" />
        <property name="serverPort" value="8880" />
        </properties>
        <!-- JAX-WS Transport
     <proxyTransport>org.apache.juddi.v3.client.transport.JAXWSTransport</proxyTransport>
        <custodyTransferUrl>http://${serverName}:${serverPort}/juddiv3/services/custody-transfer?wsdl</custodyTransferUrl>
    <inquiryUrl>http://${serverName}:${serverPort}/juddiv3/services/inquiry?wsdl</inquiryUrl>
    <publishUrl>http://${serverName}:${serverPort}/juddiv3/services/publish?wsdl</publishUrl>
    <securityUrl>http://${serverName}:${serverPort}/juddiv3/services/security?wsdl</securityUrl>
    <subscriptionUrl>http://${serverName}:${serverPort}/juddiv3/services/subscription?wsdl</subscriptionUrl>
    <subscriptionListenerUrl>http://${serverName}:${serverPort}/juddiv3/services/subscription-listener?wsdl</subscriptionListenerUrl>
       <juddiApiUrl>http://${serverName}:${serverPort}/juddiv3/services/juddi-api?wsdl</juddiApiUrl>
        -->
       <!-- In VM Transport Settings 
    <proxyTransport>org.jboss.internal.soa.esb.registry.client.JuddiInVMTransport</proxyTransport>
    <custodyTransferUrl>org.apache.juddi.api.impl.UDDICustodyTransferImpl</custodyTransferUrl>
        <inquiryUrl>org.apache.juddi.api.impl.UDDIInquiryImpl</inquiryUrl>
        <publishUrl>org.apache.juddi.api.impl.UDDIPublicationImpl</publishUrl>
    <securityUrl>org.apache.juddi.api.impl.UDDISecurityImpl</securityUrl>
    <subscriptionUrl>org.apache.juddi.api.impl.UDDISubscriptionImpl</subscriptionUrl>
    <subscriptionListenerUrl>org.apache.juddi.api.impl.UDDISubscriptionListenerImpl</subscriptionListenerUrl>
       <juddiApiUrl>org.apache.juddi.api.impl.JUDDIApiImpl</juddiApiUrl>
    -->
    <!-- RMI Transport Settings -->
<proxyTransport>org.apache.juddi.v3.client.transport.RMITransport</proxyTransport>
    <custodyTransferUrl>/juddiv3/UDDICustodyTransferService</custodyTransferUrl>
    <inquiryUrl>/juddiv3/UDDIInquiryService</inquiryUrl>
    <publishUrl>/juddiv3/UDDIPublicationService</publishUrl>
<securityUrl>/juddiv3/UDDISecurityService</securityUrl>
<subscriptionUrl>/juddiv3/UDDISubscriptionService</subscriptionUrl>
<subscriptionListenerUrl>/juddiv3/UDDISubscriptionListenerService</subscriptionListenerUrl>
<juddiApiUrl>/juddiv3/JUDDIApiService</juddiApiUrl>
<javaNamingFactoryInitial>org.jnp.interfaces.NamingContextFactory</javaNamingFactoryInitial>
    <javaNamingFactoryUrlPkgs>org.jboss.naming</javaNamingFactoryUrlPkgs>
    <javaNamingProviderUrl>jnp://localhost:1099</javaNamingProviderUrl>
    </node>

As seen above, a transport should specify a proxyTransport, a URL for all of the supported UDDI API (inquiry, publish, security, subscription, subscription-listener, custodytransfer), and a jUDDI API URL. The RMI transport also includes JNDI settings. By default, the RMI settings are enabled – to switch transports you can comment them out and enable whichever of the transports you choose.

Property: org.jboss.soa.esb.scout.proxy.transportClass

When using Scout with jUDDI there is an additional parameter that one can set. This is the transport class that should be used for communication between Scout and jUDDI. Thus far there are 4 implementations of this class which are based on SOAP, SAAJ, RMI and Local (embedded java). If you are using Scout to communicate with jUDDI v3, we suggest leaving the transportClass as LocalTransport and using jUDDI's uddi.xml to use jUDDI's transports (InVM, RMI, WS).

However, when communicating with another UDDI registry (Systinet, SOA Software, etc), it is preferable to use scout's JAXR transports. There are 4 implementations of this class which are based on SOAP, SAAJ, RMI and Local (embedded java). Note that when you change the transport, you will also have to change the query and lifecycle URIs. For example:


For jUDDI we have two requirements that need to be fulfilled:

  1. access to the jUDDI database. You will need to create a schema in your database, and add the jbossesb publisher. The product/install/jUDDI-registry directory contains db create scripts for you favorite database.

  2. esb.juddi.xml and esb.juddi.client.xml. The configuration of jUDDI itself.

Note

The database can be automatically created if the user you have created has enough rights to create tables. jUDDI should be able to create a database for any database that has a Hibernate dialect associated with it.

As mentioned before, by default the JBossESB is configured to use the JAXR API using Scout as its implementation and jUDDI as the registry. Here are some examples of how you can deploy this combo.

All ESB components (with components we really mean JVMs in this case) can embed the registry and they all can connect to the same database (or different once if that makes sense).


Properties example:


<properties name="registry">

        <property name="org.jboss.soa.esb.registry.implementationClass"                     
        value="org.jboss.internal.soa.esb.services.registry.JAXRRegistryImpl"/>

        <property name="org.jboss.soa.esb.registry.factoryClass"                    
        value="org.apache.ws.scout.registry.ConnectionFactoryImpl"/>

        <property name="org.jboss.soa.esb.registry.queryManagerURI"                 
        value="org.apache.juddi.registry.local.InquiryService#inquire"/>

        <property name="org.jboss.soa.esb.registry.lifeCycleManagerURI" 
        value="org.apache.juddi.registry.local.PublishService#publish"/>

        <property name="org.jboss.soa.esb.registry.securityManagerURI" 
        value="org.apache.juddi.registry.local.SecurityService#secure"/>

        <property name="org.jboss.soa.esb.registry.user" value="jbossesb"/>
        <property name="org.jboss.soa.esb.registry.password" value="password"/>
        
        <property name="org.jboss.soa.esb.scout.proxy.transportClass"                                                   
        value="org.apache.ws.scout.transport.LocalTransport"/>

</properties>

Deploy a version of the jUDDI that brings up an RMI service. The JBossESB deploys the RMI service by default – it starts the registry within the jbossesb.sar.

The jbossesb.sar also registers a RMI service.


Properties example:


<properties name="registry">
  <property name="org.jboss.soa.esb.registry.implementationClass"
    value="org.jboss.internal.soa.esb.services.registry.JAXRRegistryImpl"/>

  <property name="org.jboss.soa.esb.registry.factoryClass"
    value="org.apache.ws.scout.registry.ConnectionFactoryImpl"/>

  <property name="org.jboss.soa.esb.registry.queryManagerURI"
    value="jnp://localhost:1099/InquiryService?org.apache.juddi.registry.rmi.Inquiry#inquire"/>

  <property name="org.jboss.soa.esb.registry.lifeCycleManagerURI"
    value="jnp://localhost:1099/PublishService?org.apache.juddi.registry.rmi.Publish#publish"/>      
  <property name="org.jboss.soa.esb.registry.securityManagerURI"
    value="jnp://localhost:1099/PublishService?org.apache.juddi.registry.rmi.Publish#publish"/>
  
  <property name="org.jboss.soa.esb.registry.user" value="jbossesb"/>
  <property name="org.jboss.soa.esb.registry.password" value="password"/>
      
  <property name="org.jboss.soa.esb.scout.proxy.transportClass"
    value="org.apache.ws.scout.transport.RMITransport"/>
</properties>

The juddi.war is configured to bring up a RMI Service, which is triggered by the following setting in the web.xml


<!--  uncomment if you want to enable making calls in juddi with rmi  -->
  <servlet>
    <servlet-name>RegisterServicesWithJNDI</servlet-name>
    <servlet-class>org.apache.juddi.registry.rmi.RegistrationService</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

Make sure to include, for example, the following JNDI settings in your juddi.properties:

# JNDI settings (used by RMITransport)

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming

Important

The RMI clients need to have the scout-client.jar in their classpath.

If you don't want to deploy the juddi.war you can setup one of the ESB components that runs in the the same JVM as jUDDI to register the RMI service. While the other applications need to be configured to use RMI.


Properties example: For application 1 you need the Local settings:


<properties name="registry">
    <property name="org.jboss.soa.esb.registry.implementationClass" 
value="org.jboss.internal.soa.esb.services.registry.JAXRRegistryImpl"/>

    <property name="org.jboss.soa.esb.registry.factoryClass"
value="org.apache.ws.scout.registry.ConnectionFactoryImpl"/>

        <property name="org.jboss.soa.esb.registry.queryManagerURI"
value="org.apache.juddi.registry.local.InquiryService#inquire"/>

        <property name="org.jboss.soa.esb.registry.lifeCycleManagerURI"
value="org.apache.juddi.registry.local.PublishService#publish"/>

        <property name="org.jboss.soa.esb.registry.securityManagerURI"
value="org.apache.juddi.registry.local.SecurityService#secure"/>

        <property name="org.jboss.soa.esb.registry.user" value="jbossesb"/>
        <property name="org.jboss.soa.esb.registry.password" value="password"/>
        
        <property name="org.jboss.soa.esb.scout.proxy.transportClass" 
value="org.apache.ws.scout.transport.LocalTransport"/>
</properties>

while for application2 you need the RMI settings:


<properties name="registry">
    <property name="org.jboss.soa.esb.registry.implementationClass"
value="org.jboss.internal.soa.esb.services.registry.JAXRRegistryImpl"/>

    <property name="org.jboss.soa.esb.registry.factoryClass"
value="org.apache.ws.scout.registry.ConnectionFactoryImpl"/>

        <property name="org.jboss.soa.esb.registry.queryManagerURI"
value="jnp://localhost:1099/InquiryService?org.apache.juddi.registry.rmi.Inquiry#inquire"/>

        <property name="org.jboss.soa.esb.registry.lifeCycleManagerURI"
value="jnp://localhost:1099/PublishService?org.apache.juddi.registry.rmi.Publish#publish"/>
    
        <property name="org.jboss.soa.esb.registry.user" value="jbossesb"/>
        <property name="org.jboss.soa.esb.registry.password" value="password"/>
        
        <property name="org.jboss.soa.esb.scout.proxy.transportClass"
value="org.apache.ws.scout.transport.RMITransport"/>
</properties>

Where the hostname of the queryManagerURI and lifeCycleManagerURI need to point to the hostname on which jUDDI is running (which would be where application1 is running). Obviously application1 needs to have access to a naming service. To do the registration process you need to do something like:

//Getting the JNDI setting from the config

Properties env = new Properties();
env.setProperty(RegistryEngine.PROPNAME_JAVA_NAMING_FACTORY_INITIAL,factoryInitial);
env.setProperty(RegistryEngine.PROPNAME_JAVA_NAMING_PROVIDER_URL, providerURL);
env.setProperty(RegistryEngine.PROPNAME_JAVA_NAMING_FACTORY_URL_PKGS,
  factoryURLPkgs); 
InitialContext context = new InitialContext(env);
Inquiry inquiry = new InquiryService();
log.info("Setting " + INQUIRY_SERVICE + ", " + inquiry.getClass().getName());
mInquery = inquiry;
context.bind(INQUIRY_SERVICE, inquiry);
Publish publish = new PublishService();
log.info("Setting " + PUBLISH_SERVICE + ", " + publish.getClass().getName());
mPublish = publish;
context.bind(PUBLISH_SERVICE, publish);

The JBossESB Rule Service allows you to deploy rules created in Drools as services on the ESB. This is beneficial, because it means you don't have to develop as much client code to integrate rules into your application environment, and rules can be accessed as part of an action chain or orchestrated business process. To understand these types of services, you should first learn about Drools.

Rule Services are supported by the BusinessRulesProcessor action class and the DroolsRuleService, which implement the RuleService interface. While it is possible to use rule engines other than Drools, only Drools is supported out the the box. The BusinessRulesProcessor supports rules loaded from the classpath that are defined in .drl files, .dsl files (domain specific language support), and .xls (decision table support) files. These are primarily for testing, prototypes, and very simple rule services. There is no way to specify multiple rule files in the jboss-esb.xml file, so complex rule services need to use the Drools KnowledgeAgent.

The RuleService uses the KnowledgeAgent to access rule packages from the Drools BRMS or local file system. These rule packages can contain thousands of rules, the source of which can be:

The BusinessRulesProcessor action supports both Drools stateless and stateful execution models. Most rule services will be stateless. That is, a message will be sent to the rule service that includes all the facts to be inserted into the rule engine in the message body, the rules will execute, updating either the message and / or the facts. Stateful execution takes place over time, with several messages being sent to the rule service, the rules being executed each time, the message and / or facts being updated each time, and a final message that tells the rule service to dispose of the stateful session working memory of the rule engine. There are limitations in this configuration, namely that there can only be a single (stateful) rule service in the message flow. This may change in the future, when there are better ways to identify a stateful conversation over the ESB.

A rule set can be created using the JBoss Developer Studio which includes a plug-in for Drools, or with Eclispe 3.5 and the plugin installed (see Drools download site for the plugin). Since the message is added as a global, you need to add jbossesb-rosetta.jar to your Drools project.

You can also write your rules using the Drools BRMS Business Rule Editor. When using the Drools BRMS, it is not necessary to add the ESB Message class to the imports, as long as jbossesb-rosetta.jar is somewhere on the classpath of the BRMS web application.

For the most part, rules can be written without regard to their deployment on the ESB as a service. There are a few caveats however:

The consumer of a rule service has little to worry about. In a rule service environment there is no need for the consumer to worry about creating rulebases, creating working memories, inserting facts, or firing the rules. Instead the consumer just has to worry about adding facts to the message, and possibly some properties to the message.

In some cases the client is ESB aware, and will add the objects to the message directly:

MessageFactory factory = MessageFactory.getInstance();

message = factory.getMessage(MessageType.JAVA_SERIALIZED);
order = new Order();
order.setOrderId(0);
order.setQuantity(20);
order.setUnitPrice(new Float("20.0"));
message.getBody().add("Order", order);

In other cases the data may be in an XML message, and a transformation service will be added to the message flow to transform the XML to POJOs before the rule service is invoked.

Using stateful rule execution requires a few properties to be added the messages. For the first message,

message.getProperties().setProperty("dispose", false);

message.getProperties().setProperty("continue", false);

For all the subsequest messages but the final message,

message.getProperties().setProperty("dispose", false);

message.getProperties().setProperty("continue", true);

For the final message:

message.getProperties().setProperty("dispose", true); 

message.getProperties().setProperty("continue", true);

These can be added directly by an ESB aware client. A non-ESB aware client would have to communicate the position of the message (first, ongoing, last) in the data, and an action class would need to be added to the pipeline to add the properties to the ESB message (see quickstarts/business_ruleservice_stateful for an example of this type of service).

Configuration of a rule service is in the jboss-esb action element for the service. Several configuration parameters are required or optional

The action class and name is required:


<action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
  name="OrderDiscountRuleService">

This configures the action class and its name. The name is user defined.

One of the following is also required:


<property name="ruleSet" value="drl/OrderDiscount.drl" />

for specifying a drl file, or


<property name="ruleSet" value="dsl/approval.dslr" />
<property name="ruleLanguage" value="dsl/acme.dsl" />

for specifying a dsl and dslr (domain specific language) files , or


<property name="decisionTable" value="PolicyPricing.xls" />

or specifying a decisionTable on the classpath, or


<property name="ruleAgentProperties"
           value="brmsdeployedrules.properties" />

for specifying a properties file on the classpath that tells the rule agent how to find the rule package. This could specify a url or a local file system.

Several example configurations follow.

  1. Rules are in a drl, execution is stateless:

    
    <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
      name="OrderDiscountRuleService">
        <property name="ruleSet" value="drl/OrderDiscount.drl" />
        <property name="ruleReload" value="true" />
        <property name="object-paths">
            <object-path esb="body.Order" />
        </property>
    </action>
  2. Rules are in a drl, execution is stateful.

    In this scenario, a service may receive multiple messages over time and wish to use rules to accumulate data across this message set. Each time a message is received, the rules will be fired within the context of a single Stateful Session. The active Session can be disposed of (reset) via the “dispose” property.

    
    <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
      name="OrderDiscountMultipleRuleServiceStateful">
        <property name="ruleSet"
                  value="drl/OrderDiscountOnMultipleOrders.drl" />
        <property name="ruleReload" value="false" />
        <property name="stateful" value="true" >
        <property name="object-paths">
            <object-path esb="body.Customer" />
            <object-path esb="body.Order" />
        </property>
    </action>
  3. Rules are in a drl, execution is stateful, audit logging is enabled, and the Drools clockType, eventProcessingType and channels are set to aid in Complex Event Processing (CEP). KnowledgeBase partitioning is not enabled since ruleMultithreadEvaluation if false (also note ruleMaxThreads is 1).

    In this scenario, a service may want to perform Drools audit logging so that the Drools Eclipse editor can parse the audit file for debugging. It also wants to specify a specific clock type or event processing type for CEP. Last it wants to specify Drools "Channels" to send Objects to ("Channels" used to be known as "ExitPoints").

    
    <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
      name="OrderEventsRuleServiceStateful">
        <property name="ruleSet" value="drl/OrderEvents.drl" />
        <property name="ruleReload" value="false" />
        <property name="stateful" value="true" >
        <property name="ruleFireMethod" value="FIRE_UNTIL_HALT" />
        <property name="ruleAuditType" value="THREADED_FILE" />
        <property name="ruleAuditFile" value="myaudit" />
        <property name="ruleAuditInterval" value="1000" />
        <property name="ruleClockType" value="REALTIME" />
        <property name="ruleEventProcessingType" value="STREAM" />
        <property name="ruleMultithreadEvaluation" value="false" />
        <property name="ruleMaxThreads" value="1" />
        <property name="object-paths">
            <object-path esb="body.OrderStatus"
                entry-point="OrderStatusStream" />
            <object-path esb="body.OrderInfo"
                entry-point="OrderInfoStream" />
        </property>
        <property name="channels">
            <!-- chan1 and chan2 are equivalent
                (but timeout only applies if async is false) -->
            <send-to channel-name="chan1"
                service-category="cat1" service-name="svc1" />
            <send-to channel-name="chan2"
                service-category="cat1" service-name="svc1"
                channel-class="org.jboss.soa.esb.services.rules.ServiceChannel"
                async="true" timeout="30000"
                set-payload-location="org.jboss.soa.esb.message.defaultEntry" />
            <!-- chan3 is a custom channel -->
            <send-to channel-name="chan3"
                channel-class="com.example.MyChannel" />
        </property>
    </action>
  4. Rules are in a Domain Specific Language, execution is stateless:

    
    <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
      name="PolicyApprovalRuleService">
        <property name="ruleSet" value="dsl/approval.dslr" />
        <property name="ruleLanguage" value="dsl/acme.dsl" />
        <property name="ruleReload" value="true" />
        <property name="object-paths">
            <object-path esb="body.Driver" />
            <object-path esb="body.Policy" />
        </property>
    </action>
  5. Rules are in a DecisionTable, execution is stateless:

    
    <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
      name="PolicyPricingRuleService">
        <property name="decisionTable"
                  value="decisionTable/PolicyPricing.xls" />
        <property name="ruleReload" value="true" />
        <property name="object-paths">
            <object-path esb="body.Driver" />
            <object-path esb="body.Policy" />
        </property>
    </action>
  6. Rules are in the BRMS, execution is stateless.

    
    <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor"
      name="RuleAgentPolicyService">
        <property name="ruleAgentProperties"
                  value="ruleAgent/brmsdeployedrules.properties" />
        <property name="object-paths">
            <object-path esb="body.Driver" />
            <object-path esb="body.Policy" />
        </property>
    </action>

The action attributes to the action tag are show in Table 1. The attributes specify which action is to be used and which name this action is to be given.

The action properties are shown in Table 2. The properties specify the set of rules (ruleSet) to be used in this action.

location.objectname.[beanname].[beanname]...

where,

examples:

Finally, the Object Mapper can flatten out entire collections. For example a collectoin Orders will be unrolled, and each order object inserted into working memory.

To send an Object to a Drools Channel in DRL, the syntax is very simple and goes on the RHS (Right Hand Side) of the rule definition:

channels["mychannel"].send(myobject);

For this DRL to be functional, the "mychannel" channel needs to be registered to do this you add a "channels" property section to the jboss-esb.xml configuration. You can define as many Channels as you want, for the same or for different Channel names. (For a particular Channel name, the Channels will be executed in the same order as they appear in the configuration.) The types of Channels supported are:

Typically, information within the ESB is conveniently packaged, transferred, and stored in the form of a message. Messages are addressed to Endpoint References (services or clients), that identify the machine/process/object that will ultimately deal with the content of the message. However, what happens if the specified address is no longer valid? For example, the service has failed or been removed from service? It is also possible that the service no longer deals with messages of that particular type; in which case, presumably some other service still handles the original function, but how should the message be handled? What if other services besides the intended recipient are interested in the message's content? What if no destination is specified?

One possible solution to these problems is Content-Based Routing. Content-based routing seeks to route messages, not by a specified destination, but by the actual content of the message itself. In a typical application, a message is routed by opening it up and applying a set of rules to its content to determine the parties interested in its content.

The ESB can determine the destination of a given message based on the content of that message, freeing the sending application from having to know anything about where a message is going to end up.

Content-based routing and filtering networks are extremely flexible and very powerful. When built upon established technologies such as MOM (Message Oriented Middleware), JMS (Java Message Services), and XML (Extensible Markup Language) they are also reasonably easy to implement.

JBossESB ships with three slightly different routing action classes. Each of these action classes implements an Enterprise Integration Pattern. For more information of the Enterprise Integration Pattern you can check the JBossESB Wiki. The following actions are supported:

For XML-based messages it is convenient to do XPath based evaluation. To support this we ship a “Domain Specific Language” implementation which allows us to use XPath expressions in the rule file. defined in the XPathLanguage.dsl. To use it you need to reference it in your ruleSet with:

expander XPathLanguage.dsl

Currently the XPath Language makes sure the message is of the type JBOSS_XML and it defines

Now that we have seen all the individual pieces how does it all tie together? It basically all comes down to configuration at this point, which is all done in your jboss-esb.xml. The image shows a service configuration fragment. In this fragment the service is listening on a JMS queue.

Each EsbMessage is passed on to in this case the ContentBasedRouter action class which is loaded with a certain rule set. It sets the EsbMessage into Working Memory, fires the rules, obtains the list of destinations and routes copies of the EsbMessage to these services. It uses the rule set JbossESBRules.drl, which matches two destinations, name 'xml-destination' and 'serialized-destination'. These names are mapped to real service names in the 'route-to' section.


<service 
            category="MessageRouting" 
            name="YourServiceName" 
            description="CBR Service">
            <listeners>        
                  <jms-listener name="CBR-Listener"                  
                            busidref="QueueA" maxThreads="1">             
               </jms-listener>
               </listeners>
        <actions> 
             <action class="org.jboss.soa.esb.actions.ContentBasedRouter" 
                                 name="YourActionName">
                        <property name="ruleSet" value="JBossESBRules.drl"/>
                        <property name="ruleReload" value="true"/>
                        <property name="destinations">
                           <route-to destination-name="xml-destination" 
                    service-category="category01" 
                       service-name="jbossesbtest1" /> 
                           <route-to destination-name="serialized-destination"
                                                       service-category="category02" 
                    service-name="jbossesbtest2" /> 
                        </property> 
                        <property name="object-paths">
                <object-path esb="body.test1" /> 
                <object-path esb="body.test2" /> 
                </property>
                    </action>
        </actions>
            </service>

The action attributes to the action tag are show in the table below. The attributes specify which action is to be used and which name this action is to be given.


The action properties are shown in the next table. The properties specify the set of rules (ruleSet) to be used in this action.

Table 3.2. Action Configuration Properties

PropertyDescription
ruleSet Name of the filename containing the Drools ruleSet. The set of rules that is used to evaluate the content. Only 1 ruleSet can be given for each CBR instance.
ruleLanguage Optional reference to a file containing the definition of a Domain Specific Language to be used for evaluating the rule set.
ruleAgentProperties This property points to a rule agent properties file located on the classpath. The properties file can contain a property that points to precompiled rules packages on the file system, in a directory, or identified by an URL for integration with the BRMS. See the “KnowledgeAgent” section below for more information.
ruleReload Optional property which can be to true to enable 'hot' redeployment of rule sets. Note that this feature will cause some overhead on the rules processing. Note that rules will also reload if the .esb archive in which they live is redeployed.
stateful Optional property which tells the RuleService to use a stateful session where facts will be remembered between invokations. See the “Stateful Rules” section for more information about stateful rules.
destinations A set of route-to properties each containing the logical name of the destination along with the Service category and name as referenced in the registry. The logical name is the name which should be used in the rule set.
object-paths Optional property to pass Message objects into Drools WorkingMemory.
ruleAuditTypeOptional property to have Drools perform audit logging. The log can be read into the Drools Eclipse plugin and inspected. Valid values are CONSOLE, FILE and THREADED_FILE. The default is that no audit logging will be performed.
ruleAuditFileOptional property to define the filepath for audit logging. Only applies to FILE or THREADED_FILE ruleAuditType. The default is "event". Note that JBoss Drools will append ".log" for you. The default location for this file is "." - the current working directory (which for JBoss is in its bin/ directory).
ruleAuditIntervalOptional property to define how often to flush audit events to the audit log. Only applies to the THREADED_FILE ruleAuditType. The default is 1000 (milliseconds).

It is recommended that you package up your code into units of functionality, using .esb packages. The idea is to package up your routing rules alongside the rule services that use the rule sets. The example below shows a layout of the simple_cbr quickstart to demonstrate a typical package.


  simple_cbr.esb
|   jbm-queue-service.xml
|   SimpleCBRRules-XPath.drl
|   SimpleCBRRules.drl
|   
+---META-INF
|       deployment.xml
|       jboss-esb.xml
|       MANIFEST.MF
|       
\---org
    \---jboss
        \---soa
            \---esb
                \---samples
                    \---quickstart
                        \---simplecbr
                            |   MyJMSListenerAction.class
                            |   ReturnJMSMessage.class
                            |   RouteExpressShipping.class
                            |   RouteNormalShipping.class
                            |   
                            \---test
                                    ReceiveJMSMessage$1.class
                                    ReceiveJMSMessage.class
                                    SendJMSMessage.class

Finally make sure to deploy and reference the jbrules.esb in your deployment.xml.


<jbossesb-deployment>
 <depends>jboss.esb:deployment=jbrules.esb</depends>
</jbossesb-deployment>

The SmooksAction can be used for splitting HUGE messages into split fragments and performing Content-Based Routing on these split fragments.

An example of this might be a huge order message with thousands/millions of order items per message. You might need to split the order up by order item and route each order item split fragment to one or more destinations based on the fragment content. This example can be illustrated as follows:


The above illustration shows how we would like to perform the by-order-item splitting operation and route the split messages to file. The split messages contain a full XML document with data merged from the order header and the order item in question i.e. not just a dumb split. In this illustration, we simply route all the message fragments to file, but with the Smooks Action, we can also route the fragment messages to JMS and to a Database and in different formats (EDI, populated Java Objects, etc).

The Smooks configuration for the above example would look as follows.


(1) <jb:bindings beanId="order" class="java.util.HashMap" createOnElement="order">
        <jb:value property="orderId" decoder="Integer" data="order/@id"/>
        <jb:value property="customerNumber" decoder="Long" data="header/customer/@number"/>
        <jb:value property="customerName" data="header/customer"/>
        <jb:wiring property="orderItem" beanIdRef="orderItem"/>
    </jb:bindings>
(2) <jb:bindings beanId="orderItem" class="java.util.HashMap" createOnElement="order-item">
        <jb:value property="itemId" decoder="Integer" data="order-item/@id"/>
        <jb:value property="productId" decoder="Long" data="order-item/product"/>
        <jb:value property="quantity" decoder="Integer" data="order-item/quantity"/>
        <jb:value property="price" decoder="Double" data="order-item/price"/>
    </jb:bindings>

(3) <file:outputStream openOnElement="order-item" resourceName="orderItemSplitStream">
        <file:fileNamePattern>
            order-${order.orderId}-${order.orderItem.itemId}.xml
        </file:fileNamePattern>
        <file:destinationDirectoryPattern>target/orders</file:destinationDirectoryPattern>
        <file:listFileNamePattern>order-${order.orderId}.lst</file:listFileNamePattern>

        <file:highWaterMark mark="3"/>
    </file:outputStream>

(4) <ftl:freemarker applyOnElement="order-item">
        <ftl:template>target/classes/orderitem-split.ftl</ftl:template>
        <ftl:use>
            <ftl:outputTo outputStreamResource="orderItemSplitStream"/>
        </ftl:use>
    </ftl:freemarker>

Resource configurations #1 and #2 are there to bind data from the source message into Java Objects in the Smooks bean context. In this case, we're just binding the data into HashMaps. The Map being populated in configuration #2 is recreated and repopulated for every order item as the message is being filtered. The populated Java Objects (from resources #1 and #2) are used to populate a FreeMarker template (resource #4), which gets applied on every order item, with the result of the templating operation being output to a File OutputStream (resource #3). The File OutputStream (resource #3) also gets applied on every order item, managing the file output for the split messages.

What the above does not show is how to perform the content based routing using <condition> elements on the resources. It also doesn't demonstrate how to route fragments to to message aware endpoints. We will be adding a quickstart dedicated to demoing these features of the ESB. Check the User Forum for details.

JBossESB 4.8 upgrades to Smooks v1.1, which means that the split described above can be done without having to define the binding configurations (#1 and #2). For more on how to do this, see the documentation on “FreeMarker Transforms using NodeModels” in section 4 of the Smooks User Guide.



[1] Note that some of the ESB Quickstarts are still using the older “SmooksTransformer” action class. The SmooksAction is a more flexible and easier to use alternative to the SmooksTransformer. The SmooksTransformer will be deprecated in a future release (and removed later again).

The jbpm.esb deployment that ships with the ESB includes the full jBPM runtime and the jBPM console. The runtime and the console share a common jBPM database. The ESB DatabaseInitializer mbean creates this database on startup. The configuration for this mbean is found in the file jbpm.esb/jbpm-service.xml.


<classpath codebase="deploy" archives="jbpm.esb"/>
<classpath codebase="deploy/jbossesb.sar/lib" 
   archives="jbossesb-rosetta.jar"/>

<mbean code="org.jboss.internal.soa.esb.dependencies.DatabaseInitializer"
   name="jboss.esb:service=JBPMDatabaseInitializer">
   <attribute name="Datasource">java:/JbpmDS</attribute>
   <attribute name="ExistsSql">select * from JBPM_ID_USER</attribute>
   <attribute name="SqlFiles">
       jbpm-sql/jbpm.jpdl.hsqldb.sql,jbpm-sql/import.sql
   </attribute>
   <depends>jboss.jca:service=DataSourceBinding,name=JbpmDS</depends>
</mbean>

<mbean code="org.jboss.soa.esb.services.jbpm.configuration.JbpmService"
   name="jboss.esb:service=JbpmService">
</mbean>

The first Mbean configuration element contains the configuration for the DatabaseInitializer. By default the attributes are configured as follows:


The DatabaseInitializer mbean is configured in jbpm-service.xml to wait for the JbpmDS to be deployed, before deploying itself. The second mbean “JbpmService” ties the lifecycle of the jBPM job executor to the jbpm.esb lifecycle - it starts a job executor instance on startup and stops it on shutdown. The JbpmDS datasource is defined in the jbpm-ds.xml and by default it uses a HSQL database. In production you will want change to a production strength database. All jbpm.esb deployments should share the same database instance so that the various ESB nodes have access to the same processes definitions and instances.

The jBPM console is a web application accessible at http://localhost:8080/jbpm-console, when you start the server. The login screen is shown below.


Please check the jBPM documentation [TB-JBPM-USER] to change the security settings for this application, which will involve change some settings in the conf/login-config.xml. The console can be used for deploying and monitoring jBPM processes, but is can also be used for human task management. For the different users a customized task list will be shown and they can work on these tasks. The quickstart bpm_orchestration4 [JBESB-QS] demonstrates this feature.

The jbpm.esb/META-INF directory contains the deployment.xml and the jboss-esb.xml. The deployment.xml specifies the resources this esb archive depends on:


<jbossesb-deployment>
  <depends>jboss.esb:deployment=jbossesb.esb</depends>
  <depends>jboss.jca:service=DataSourceBinding,name=JbpmDS</depends>
</jbossesb-deployment>

The jboss-esb.xml file deploys one internal service, called JBpmCallbackService:


<services>
  <service category="JBossESB-Internal" name="JBpmCallbackService"
    description="Service which makes Callbacks into jBPM">
    <listeners>
      <jms-listener name="JMS-DCQListener" 
        busidref="jBPMCallbackBus" maxThreads="1" />
    </listeners>
    <actions mep="OneWay">
      <action name="action" 
        class="org.jboss.soa.esb.services.jbpm.actions.JBpmCallback"/>
    </actions>
  </service>
</services>

This service listens to the jBPMCallbackBus, which by default is a JMS Queue on either a JBossMQ (jbmq-queue-service.xml) or a JBossMessaging (jbm-queue-service.xml) messaging provider. Make sure only one of these files gets deployed in your jbpm.esb archive. If you want to use your own provider simple modify the provider section in the jboss-esb.xml to reference your JMS provider. shown in this example:


<providers>
  <jms-provider name="CallbackQueue-JMS-Provider" 
    connection-factory="ConnectionFactory">
    <jms-bus busid="jBPMCallbackBus">
      <jms-message-filter dest-type="QUEUE" 
        dest-name="queue/CallbackQueue" />
    </jms-bus>
  </jms-provider>
</providers>

Note

For more details on what the JbpmCallbackService does, please see the “jBPM to ESB” section later on in this chapter.

The configuration of jBPM itself is managed by three files, the jbpm.cfg.xml and the hibernate.cfg.xml and the jbpm.mail.templates.xml.

By default the jbpm.cfg.xml is set to use the JTA transacion manager, as defined in the section:


<service name="persistence">
  <factory>
    <bean class="org.jbpm.persistence.jta.JtaDbPersistenceServiceFactory">
      <field name="isTransactionEnabled"><false/></field>
      <field name="isCurrentSessionEnabled"><true/></field>
      <!--field name="sessionFactoryJndiName">
      <string value="java:/myHibSessFactJndiName" />
      </field-->
    </bean>
  </factory>
</service>

Other settings are left to the default jBPM settings.

The hibernate.cfg.xml is also slightly modified to use the JTA transaction manager


<!-- JTA transaction properties (begin) ===
    ==== JTA transaction properties (end) -->
<property name="hibernate.transaction.factory_class">
  org.hibernate.transaction.JTATransactionFactory</property>

<property name="hibernate.transaction.manager_lookup_class">
  org.hibernate.transaction.JBossTransactionManagerLookup</property>

Hibernate is not used to create the database schema, instead we use our own DatabaseInitiazer mbean, as mentioned in the previous section.

The jbpm.mail.templates.xml is left empty by default. For each more details on each of these configuration files please see the jBPM documentation.

To create a Process Definition we recommend using the eclipse based jBPM Process Designer Plugin [KA-JBPM-GPD]. You can either download and install it to eclipse yourself, or use JBoss Developer Studio. The image below shows the graphical editor.


The graphical editor allows you to create a process definition visually. Nodes and transitions between nodes can be added, modified or removed. The process definition saves as an XML document which can be stored on a file system and deployed to a jBPM instance (database). Each time you deploy the process instance jBPM will version it and will keep the older copies. This allows processes that are in flight to complete using the process instance they were started on. New process instances will use the latest version of the process definition.

To deploy a process definition the server needs to be up and running. Only then can you go to the 'Deployment' tab in the graphical designer to deploy a process archive (par). Figure 3 shows the “Deployment” tab view.


In some cases it would suffice to deploy just the processdefinition.xml, but in most cases you will be deploying other type of artifacts as well, such as task forms. It is also possible to deploy Java classes in a par, which means that they end up in the database where they will be stored and versioned. However it is strongly discouraged to do this in the ESB environment as you will risk running into class loading issues. Instead we recommend deploying your classes in the lib directory of the server. You can deploy a process definition

  1. straight from the eclipse plugin, by clicking on the “Test Connection..” button and, on success, by clicking on the “Deploy Process Archive” button,

  2. by saving the deployment to a par file and using the jBPM console to deploy the archive, see Figure 4, or finally,

  3. by using the DeployProcessToServer jBPM ant task.


JBossESB can make calls into jBPM using the BpmProcessor action. This action uses the jBPM command API to make calls into jBPM. The following jBPM commands have been implemented:


The configuration for this action in the jboss-esb.xml looks like


<action name="create_new_process_instance" 
  class="org.jboss.soa.esb.services.jbpm.actions.BpmProcessor">

  <property name="command" value="StartProcessInstanceCommand" />
  <property name="process-definition-name" value="processDefinition2"/>
  <property name="actor" value="FrankSinatra"/>                                                 
  
  <property name="esbToBpmVars">
  <!-- esb-name maps to getBody().get("eVar1") -->
    <mapping esb="eVar1" bpm="counter" default="45" />
    <mapping esb="BODY_CONTENT" bpm="theBody" />
  </property>             

</action>

There are two required action attributes:

  1. name

    Required attribute. You are free to use any value for the name attribute as long as it is unique in the action pipeline.

  2. class

    Required attribute. This attributes needs to be set to “org.jboss.soa.esb.services.jbpm.actions.BpmProcessor”

Furthermore one can configure the following configuration properties:

Table 5.3. Configuration Properties

PropertyDescriptionRequired?
command

Needs to be one of: NewProcessInstanceCommand, StartProcessInstanceCommand, GetProcessInstanceVariablesCommand or CancelProcessInstanceCommand.

Yes

process-definition-name

required property for the NewProcessInstanceCommand and StartProcessInstanceCommand if the process-definition-id property is not used. The value of this property should reference a process definition that is already deployed to jBPM and of which you want to create a new instance. This property does not apply to the CancelProcessInstanceCommand.

Sometimes

process-definition-id

required property for the NewProcessInstanceCommand and StartProcessInstanceCommand if the process-definition-name property is not used. The value of this property should reference a process definition id in jBPM of which you want to create a new instance. This property does not apply to the CancelProcessInstanceCommand.

Sometimes

actor

specifies the jBPM actor id, which applies to the NewProcessInstanceCommand and StartProcessInstanceCommand only.

No

key

optional property to specify the value of the jBPM key. For example one can pass a unique invoice id as the value for this key. On the jBPM side this key is as the “business” key id field. The key is a string based business key property on the process instance. The combination of business key + process definition must be unique if a business key is supplied. The key value can hold an MVEL expression to extract the desired value from the EsbMessage. For example if you have a named parameter called “businessKey” in the body of your message you would use “body.businessKey”. Note that this property is used for the NewProcessInstanceCommand and StartProcessInstanceCommand only.

No

transition-name

This property only applies to the StartProcessInstanceCommand, and is of use only if there are more then one transition out of the current node. If this property is not specified the default transition out of the node is taken. The default transition is the first transition in the list of transition defined for that node in the jBPM processdefinition.xml.

No

esbToBpmVars

optional property for the NewProcessInstanceCommand and StartProcessInstanceCommand. This property defines a list of variables that need to be extracted from the EsbMessage and set into jBPM context for the particular process instance. The list consists of mapping elements. Each mapping element can have the following attributes:

  • esb

    required attribute which can contain an MVEL expression to extract a value anywhere from the EsbMessage.

  • bpm

    optional attribute containing the name which be used on the jBPM side. If omitted the esb name is used.

  • default

    optional attribute which can hold a default value if the esb MVEL expression does not find a value set in the EsbMessage.

  • bpmToEsbVars

    structurally identical to the “esbToBpmVars” property (above). Used with the GetProcessInstanceVariablesCommand for mapping jBPM process instance variables (root token variables) onto the ESB message.

  • reply-to-originator

    Optional property for the NewProcessInstanceCommand and StartProcessInstanceCommand. If this property is specified, with a value of true, then the creation of the process instance will store the ReplyTo/FaultTo EPRs of the invoking message within the process instance. These values can then be used within subsequent EsbNotifier/EsbActionHandler invocations to deliver a message to the ReplyTo/FaultTo addresses.

No


Finally some variables can be set on the body of the EsbMessage:


The JBossESB to jBPM maybe interesting but the other way around is probably far more interesting jBPM to JBossESB communication provides us with the capability to use jBPM for service orchestration. Service Orchestration itself will be discussed in more detail in the next chapter and here we're focusing on the details of the integration first. The integration implements two jBPM action handler classes. The classes are "EsbActionHandler" and "EsbNotifier". The EsbActionHandler is a request-reply type action, which drops a message on a Service and then waits for a response while the EsbNotifier only drops a message on a Service and continues its processing. The interaction with JBossESB is asynchronous in nature and does not block the process instance while the Service executes.

First we'll discuss the EsbNotifier as it implements a subset of the configuration of EsbActionHandler class.

The EsbNotifier action should be attached to an outgoing transition. This way the jBPM processing can move along while the request to the ESB service is processed in the background. In the jBPM processdefinition.xml we would need attach the EsbNotifier to the outgoing transition. For example the configuration for a “Ship It” node could look like:


<node name="ShipIt">
  <transition name="ProcessingComplete" to="end">
    <action name="ShipItAction" 
      class="org.jboss.soa.esb.services.jbpm.actionhandlers.EsbNotifier">
      <esbCategoryName>BPM_Orchestration4</esbCategoryName>
      <esbServiceName>ShippingService</esbServiceName>                           
      <bpmToEsbVars>
        <mapping bpm="entireCustomerAsObject" esb="customer" />
        <mapping bpm="entireOrderAsObject" esb="orderHeader" />
        <mapping bpm="entireOrderAsXML" esb="entireOrderAsXML" />
      </bpmToEsbVars>
    </action>
  </transition>
</node>

The following attributes can be specified:

The following subelements can be specified:

The EsbActionHandler is designed to work as a reply-response type call into JBossESB. The EsbActionHandler should be attached to the node. When this node is entered this action will be called. The EsbActionHandler executes and leaves the node waiting for a transition signal. The signal can come from any other thread of execution, but under normal processing the signal will be sent by the JBossESB callback Service. An example configuration for the EsbActionHandler could look like:


<action name="create_new_process_instance" 
  class="org.jboss.soa.esb.services.jbpm.actions.BpmProcessor">

  <property name="command" value="StartProcessInstanceCommand" />
  <property name="process-definition-name" value="processDefinition2"/>
  <property name="actor" value="FrankSinatra"/>                                                 
  
  <property name="esbToBpmVars">
  <!-- esb-name maps to getBody().get("eVar1") -->
    <mapping esb="eVar1" bpm="counter" default="45" />
    <mapping esb="BODY_CONTENT" bpm="theBody" />
  </property>             

</action>

The configuration for the EsbActionHandler action extends the EsbNotifier configuration. The extensions are the following subelements:


Optionally you may want to specify a timeout value for this action. For this you can use a jBPM native Timer on the node. If for example you only want to wait 10 seconds for the Service to complete you could add


<timer name='timeout' duedate='10 seconds' transition='time-out'/>

to the node element. Now if no signal is received within 10 seconds of entering this node, the transition called “time-out” is taken.

There are two types of scenarios where exceptions can arise.

  1. The first type of exception is a MessageDeliveryException which is thrown by the ServiceInvoker. If this occurs it means that delivery of the message to the ESB failed. If this happens things are pretty bad and you have probably misspelled the name of the Service you are trying to reach. This type of exception can be thrown from both the EsbNotifier as well as the EsbActionHandler. In the jBPM node one can add an http://docs.jboss.com/jbpm/v3/userguide/processmodelling.html [TB-JBPM-USER] to handle this exception.

  2. The second type of exception is when the Service received the request, but something goes wrong during processing. Only if the call was made from the EsbActionHandler does it makes sense to report back the exception to jBPM. If the call was made from the EsbNotifier jBPM processing has already moved on, and it is of little value to notify the process instance of the exception. This is why the exception-transition can only be specified for EsbAction-Handler.

To illustrate the type of error handling that is now possible using standard jBPM features we will discuss some scenarios illustrated below:

When using the EsbActionHandler action and the node is waiting for a callback, it maybe that you want to limit how long you want to wait for. For this scenario you can add a timer to the node. This is how Service1 is setup in Figure 5. The timer can be set to a certain due date. In this case it is set to 10 seconds. The process definition configuration would look like


<node name="Service1">

  <action class=
    "org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler">
    <esbCategoryName>MockCategory</esbCategoryName>
      <esbServiceName>MockService</esbServiceName>
  </action>
  
  <timer name='timeout' duedate='10 seconds' 
    transition='time-out-transition'/>
  <transition name="ok" to="Service2"></transition>
  <transition name="time-out-transition" to="ExceptionHandling"/>

</node>

Node “Service1” has 2 outgoing transitions. The first one is called “ok” while the second one is called “time-out-transition”. Under normal processing the call back would signal the default transition, which is the “ok” transition since it is defined first. However if the execution of the service takes more then 10 seconds the timer will fire. The transition attribute of the timer is set to “time-out-transition”,so this transition will be taken on time-out. In Figure 5 this means that the processing ends up in the “ExceptionHandling” node in which one can perform compensating work.


Scenario 3 is illustrated in the configuration of Service3 and the “exceptionDecision” node that follows it. The idea is that processing of Service3 completes normally and the default transition out of node Service3 is taken. However, somewhere during the Service execution an errorCode was set, and the “exceptionDecision” node checks if a variable called “errorCode” was set. The configuration would look like


<node name="Service3">
  <action class=
  "org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler">
     <esbCategoryName>MockCategory</esbCategoryName>
     <esbServiceName>MockService</esbServiceName>
     <esbToBpmVars>
        <mapping esb="SomeExceptionCode" bpm="errorCode"/>
     </esbToBpmVars>
  </action>
  <transition name="ok" to="exceptionDecision"></transition>
</node>
   
<decision name="exceptionDecision">
   <transition name="ok" to="end"></transition>
   <transition name="exceptionCondition" to="ExceptionHandling">
      <condition>#{ errorCode!=void }</condition>
   </transition>
</decision>

where the esbToBpmVars mapping element extracts the errorCode called “Some-ExceptionCode” from the EsbMessage body and sets in the jBPM context, if this “SomeExceptionCode” is set that is. In the next node “exceptionDecision” the “ok” transition is taken under normal processing, but if a variable called “errorCode” is found in the jBPM context, the “exceptionCondition” transition is taken. This is using the decision node feature of jBPM where transition can nest a condition. Here we check for the existence of the “errorCode” variable using the condition


<condition>#{ errorCode!=void }</condition>

The jbpm5.esb deployment that ships with the ESB includes the jBPM 5 runtime, a datasource, a hibernate configuration, and a JPA persistence configuration. The datasource is configured by default to use h2 as a backend database, and is used to persist session and process information.

In production you will want change from h2 to a production strength database. All jbpm5.esb deployments should share the same database instance so that the various ESB nodes have access to the same processes definitions and instances.

The jBPM 5 GWT console is a web application that is not included, but that can be optionally installed through the jBPM 5 installer. Please use the jbpm-5.2.0.Final installer as this is the version that has been tested against the ESB. You may need to make minor changes to the configuration of the JBPM 5 GWT console - you will want to change the to change the "context-root" in WEB-INF/jboss-web.xml from 'jbpm-console' to 'jbpm5-console' so that it does not conflict with the jbpm 3 version console which ships by default in the ESB.

Please check the jBPM 5 documentation to change the security settings for this application, which will involve change some settings in the conf/login-config.xml. The console can be used for deploying and monitoring jBPM processes, but it can also be used for human task management. For different users, a customized task list will be shown and they can administer those tasks.

The jbpm5.esb/META-INF directory contains the deployment.xml and the jboss-esb.xml. The deployment.xml specifies the resources this esb archive depends on:


<?xml version="1.0" encoding="UTF-8"?><jbossesb-deployment>
  <depends>jboss.esb:deployment=jbossesb.esb</depends>
  <depends>jboss.jca:name=jboss/datasources/jbpm5DS,service=DataSourceBinding</depends>
</jbossesb-deployment>

The configuration of jBPM itself is managed by two files, the persistence.xml and the hibernate.cfg.xml.

By default the persistence.xml is set to use the JTA transacion manager, as defined in the section:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                                 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
                                 http://java.sun.com/xml/ns/persistence/orm 
                                 http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
             xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/persistence">

  <persistence-unit name="jbpm5Persistence.jpa" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/jbpm5DS</jta-data-source>

    <mapping-file>META-INF/JBPMorm.xml</mapping-file>
    <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
    <class>org.drools.persistence.info.SessionInfo</class>
    <class>org.drools.persistence.info.WorkItemInfo</class>
    <properties> 
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
         <!-- for AS5 -->
         <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
    </properties>        
  </persistence-unit>
</persistence>

Other settings are left to the default jBPM settings.

Hibernate is used to create the database schema.

JBossESB can make calls into jBPM 5 using the Bpm5Processor action. This action uses the jBPM 5 command API to make calls into jBPM. The following jBPM commands have been implemented:


The configuration for this action in the jboss-esb.xml looks like


<action name="create_new_process_instance" 
  class="org.jboss.soa.esb.services.jbpm.actions.BpmProcessor">

  <property name="command" value="StartProcessInstanceCommand" />
  <property name="process-definition-name" value="processDefinition2"/>
  <property name="actor" value="FrankSinatra"/>                                                 
  
  <property name="esbToBpmVars">
  <!-- esb-name maps to getBody().get("eVar1") -->
    <mapping esb="eVar1" bpm="counter" default="45" />
    <mapping esb="BODY_CONTENT" bpm="theBody" />
  </property>             

</action>

There are two required action attributes:

  1. name

    Required attribute. You are free to use any value for the name attribute as long as it is unique in the action pipeline.

  2. class

    Required attribute. This attributes needs to be set to “org.jboss.soa.esb.services.jbpm5.actions.Bpm5Processor”

Furthermore one can configure the following configuration properties:


Finally some variables can be set in context of the EsbMessage:


JBossESB provides WS-BPEL support via its Web Service components. For details on these components and how to configure and use them, see the Message Action Guide.

Note

JBoss and JBossESB also have a special support agreement with ActiveEndpoints (http://www.active-endpoints.com/) for their award wining ActiveBPEL WS-BPEL Engine. In support of this, JBossESB ships with a Quickstart dedicated to demonstrating how JBossESB and ActiveBPEL can collaborate effectively to provide a WS-BPEL based orchestration layer on top of a set of Services that don't expose Webservice Interfaces (the “webservice_bpel” Quickstart). JBossESB provides the Webservice Integration and ActiveBPEL provides the Process Orchestration. A number of flash based walk-thrus of this Quickstart are also available online: http://labs.jboss.com/jbossesb/resources/tutorials/bpel-demos/bpel-demos.html.

Note

ActiveEndpoints WS-BPEL engine does not run on versions of JBossAS since 4.0.5. However, it can be deployed and run successfully on Tomcat as our examples illustrate.

A key component of Service Orchestration is to use a flow-chart like design tool to design and deploy processes. The jBPM IDE can be used for just this. Figure 6 shows an example of such a flow-chart, which represents a simplified order process. This example is taken from the bpm_orchestration4 quick start [JBESB-QS] which ships with JBossESB.


In the “Order Process” Diagram three of the nodes are JBossESB Services, the “Intake Order”, “Calculate Discount” and the “Ship It” nodes. For these nodes the regular “Node” type was used, which is why these are labeled with “<<Node>>”. Each of these nodes have the EsbActionHandler attached to the node itself. This means that the jBPM node will send a request to the Service and then it will remain in a wait state, waiting for the ESB to call back into the node with the response of the Service. The response of the service can then be used within jBPM context. For example when the Service of the “Intake Order” responds, the response is then used to populate the “Review Order” form. The “Review Order” node is a “Task Node”. Task Nodes are designed for human interaction. In this case someone is required to review the order before the Order Process can process.

To create the diagram above, select File > New > Other, and from the Selection wizard select “JBoss jBPM “Process Definition” as shown in below. The wizard will direct you to save the process definition. From an organizational point of view it is recommended use one directory per process definition, as you will typically end up with multiple files per process design.


After creating a new process definition. You can drag and drop any item from menu, shown in Figure 8, into the process design view. You can switch between the design and source modes if needed to check the XML elements that are being added, or to add XML fragments that are needed for the integration. Recently a new type of node was added called “ESB Service" [KA-BLOG].


Before building the “Order Process” diagram of Figure 6, we'd need to create and test the three Services. These services are 'ordinary' ESB services and are defined in the jboss-esb.xml. Check the jboss-esb.xml of the bpm_orchestration4 quick start [JBESB-QS] if you want details on them, but they only thing of importance to the Service Orchestration are the Services names and categories as shown in the following jboss-esb.xml fragment:



            <services>
  <service category="BPM_orchestration4_Starter_Service" 
  name="Starter_Service"
  description="BPM Orchestration Sample 4: Use this service to start a 
process instance">
            <!-- .... -->                       
  </service>
  <service category="BPM_Orchestration4" name="IntakeService"
  description="IntakeService: transforms, massages, calculates priority">
            <!-- .... -->
  </service>        
  <service category="BPM_Orchestration4" name="DiscountService"
    description="DiscountService">                  
  </service>        
  <service category="BPM_Orchestration4" name="ShippingService"
    description="ShippingService">          
            <!-- .... -->
  </service>            
</services>
        

These Service can be referenced using the EsbActionHandler or EsbNotifier Action Handlers as discussed in Chapter 1. The EsbActionHandler is used when jBPM expects a response, while the EsbNotifier can be used if no response back to jBPM is needed.

Now that the ESB services are known we drag the “Start” state node into the design view. A new process instance will start a process at this node. Next we drag in a “Node” (or “ESB Service “if available). Name this Node “Intake Order”. We can connect the Start and the Intake Order Node by selecting “Transition” from the menu and by subsequently clicking on the Start and Intake Order Node. You should now see an arrow connecting these two nodes, pointing to the Intake Order Node.

Next we need to add the Service and Category names to the Intake Node. Select the “Source” view. The “Intake Order Node should look like


<node name="Intake Order">
    <transition name="" to="Review Order"></transition>
</node>

and we add the EsbHandlerAction class reference and the subelement configuration for the Service Category and Name, BPM_Orchestration4 and“IntakeService” respectively


<node name="Intake Order">
  <action name="esbAction" class=
    "org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler">
    <esbCategoryName>BPM_Orchestration4</esbCategoryName>
    <esbServiceName>IntakeService</esbServiceName>
    <!-- async call of IntakeService -->
  </action>
  <transition name="" to="Review Order"></transition>
</node>

Next we want to send the some jBPM context variables along with the Service call. In this example we have a variable named “entireOrderAsXML” which we want to set in the default position on the EsbMessage body. For this to happen we add


<bpmToEsbVars>
  <mapping bpm="entireOrderAsXML" esb="BODY_CONTENT" />
</bpmToEsbVars>

which will cause the XML content of the variable “entireOrderAsXML” to end up in the body of the EsbMessage, so the IntakeService will have access to it, and the Service can work on it, by letting it flow through each action in the Action Pipeline. When the last action is reached it the replyTo is checked and the EsbMessage is send to the JBpmCallBack Service, which will make a call back into jBPM signaling the “Intake Order” node to transition to the next node (“Review Order”). This time we will want to send some variables from the EsbMessage to jBPM. Note that you can send entire objects as long both contexts can load the object's class. For the mapping back to jBPM we add an “esbToEsbVars” element. Putting it all together we end up with:


<node name="Intake Order">
<action name="esbAction" class=
 "org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler">
<esbCategoryName>BPM_Orchestration4</esbCategoryName>
<esbServiceName>IntakeService</esbServiceName>
<bpmToEsbVars>
<mapping bpm="entireOrderAsXML" esb="BODY_CONTENT" />
</bpmToEsbVars>
<esbToBpmVars>
<mapping esb="body.entireOrderAsXML" bpm="entireOrderAsXML"/>
<mapping esb="body.orderHeader" bpm="entireOrderAsObject" />
<mapping esb="body.customer" bpm="entireCustomerAsObject" />
<mapping esb="body.order_orderId" bpm="order_orderid" />
<mapping esb="body.order_totalAmount" bpm="order_totalamount" />
<mapping esb="body.order_orderPriority" bpm="order_priority" />
<mapping esb="body.customer_firstName" bpm="customer_firstName" />
<mapping esb="body.customer_lastName" bpm="customer_lastName" />
<mapping esb="body.customer_status" bpm="customer_status" />
</esbToBpmVars>
</action>
<transition name="" to="Review Order"></transition>
</node>

So after this Service returns we have the following variables in the jBPM context for this process: entireOrderAsXML, entireOrderAsObject, entireCustomerAsObject, and for demo purposes we also added some flattened variables: order_orderid, order_totalAmount, order_priority, customer_firstName, customer_lastName and customer_status.


In our Order process we require a human to review the order. We therefore add a “Task Node” and add the task “Order Review”, which needs to be performed by someone with actor_id “user”. The XML-fragment looks like


<task-node name="Review Order">
<task name="Order Review">
<assignment actor-id="user"></assignment>
 <controller>
<variable name="customer_firstName"
access="read,write,required"></variable>
<variable name="customer_lastName" access="read,write,required">
<variable name="customer_status" access="read"></variable>
<variable name="order_totalamount" access="read"></variable>
<variable name="order_priority" access="read"></variable>
<variable name="order_orderid" access="read"></variable>
<variable name="order_discount" access="read"></variable>
<variable name="entireOrderAsXML" access="read"></variable>
</controller>
</task>
<transition name="" to="Calculate Discount"></transition>
</task-node>

In order to display these variables in a form in the jbpm-console we need to create an xhtml dataform (see the Review_Order.xhtml file in the bpm_orchestration4 quick start [JBESB-QS] and tie this for this TaskNode using the forms.xml file:


<forms>
<form task="Order Review" form="Review_Order.xhtml"/>
<form task="Discount Review" form="Review_Order.xhtml"/>
</forms>

Note that in this case the same form is used in two task nodes. The variables are referenced in the Review Order form like


<jbpm:datacell>
<f:facet name="header">
<h:outputText value="customer_firstName"/>
</f:facet>
<h:inputText value="#{var['customer_firstName']}" />
</jbpm:datacell>

which references the variables set in the jBPM context.

When the process reaches the “Review Node”, as shown in Figure 9. When the 'user' user logs into the jbpm-console the user can click on 'Tasks” to see a list of tasks, as shown in below. The user can 'examine' the task by clicking on it and the user will be presented with a form as shown below. The user can update some of the values and click “Save and Close” to let the process move to the next Node.



The next node is the “Calculate Discount” node. This is an ESB Service node again and the configuration looks like


<node name="Calculate Discount">
<action name="esbAction" class="
org.jboss.soa.esb.services.jbpm.actionhandlers.EsbActionHandler">
<esbCategoryName>BPM_Orchestration4</esbCategoryName>
<esbServiceName>DiscountService</esbServiceName>
<bpmToEsbVars>
<mapping bpm="entireCustomerAsObject" esb="customer" />
<mapping bpm="entireOrderAsObject" esb="orderHeader" />
<mapping bpm="entireOrderAsXML" esb="BODY_CONTENT" />
</bpmToEsbVars>
<esbToBpmVars>
<mapping esb="order"
bpm="entireOrderAsObject" />
<mapping esb="body.order_orderDiscount" bpm="order_discount" />
</esbToBpmVars>
</action>
<transition name="" to="Review Discount"></transition>
</node>

The Service receives the customer and orderHeader objects as well as the entireOrderAsXML, and computes a discount. The response maps the body.order_orderDiscount value onto a jBPM context variable called “order_-discount”, and the process is signaled to move to the “Review Discount” task node.


The user is asked to review the discount, which is set to 8.5. On “Save and Close” the process moves to the “Ship It” node, which again is an ESB Service. If you don't want the Order process to wait for the Ship It Service to be finished you can use the EsbNotifier action handler and attach it to the outgoing transition:


<node name="ShipIt">
<transition name="ProcessingComplete" to="end">
<action name="ShipItAction" class=
"org.jboss.soa.esb.services.jbpm.actionhandlers.EsbNotifier">
<esbCategoryName>BPM_Orchestration4</esbCategoryName>
<esbServiceName>ShippingService</esbServiceName>
 <bpmToEsbVars>
<mapping bpm="entireCustomerAsObject" esb="customer" />
 <mapping bpm="entireOrderAsObject" esb="orderHeader" />
 <mapping bpm="entireOrderAsXML" esb="entireOrderAsXML" />
 </bpmToEsbVars>
 </action>
</transition>
</node>

After notifying the ShippingService the Order process moves to the 'end' state and terminates. The ShippingService itself may still be finishing up. In bpm_orchestration4 [JBESB-QS] it uses drools to determine whether this order should be shipped 'normal' or 'express'.

In the previous paragraph we create the process definition and we quietly assumed we had an instance of it to explain the process flow. But now that we have created the processdefinition.xml, we can deploy it to jBPM using the IDE, ant or the jbpm-console (as explained in Chapter 1). In this example we use the IDE and deployed the files: Review_Order.xhtml, forms.xml, gpd.xml, processdefinition.xml and the processimage.jpg. On deployment the IDE creates a par achive and deploys this to the jBPM database. We do not recommend deploying Java code in par archives as it may cause class loading issues. Instead we recommend deploying classes in jar or esb archives.


When the process definition is deployed a new process instance can be created. It is interesting to note that we can use the 'StartProcessInstanceCommand” which allows us to create a process instance with some initial values already set. Take a look at


<service category="BPM_orchestration4_Starter_Service"
name="Starter_Service"
description="BPM Orchestration Sample 4: Use this service to start a
 process instance">
<listeners>
</listeners>
<actions>
<action name="setup_key" class=
"org.jboss.soa.esb.actions.scripting.GroovyActionProcessor">
<property name="script"
value="/scripts/setup_key.groovy" />
</action>
<action name="start_a_new_order_process" class=
"org.jboss.soa.esb.services.jbpm.actions.BpmProcessor">
<property name="command"
value="StartProcessInstanceCommand" />
<property name="process-definition-name"
value="bpm4_ESBOrderProcess" />
<property name="key" value="body.businessKey" />
<property name="esbToBpmVars">
 <mapping esb="BODY_CONTENT" bpm="entireOrderAsXML" />
</property>
</action>
</actions>
</service>

where new process instance is invoked and using some groovy script, and the jBPM key is set to the value of 'OrderId' from an incoming order XML, and the same XML is subsequently put in jBPM context using the esbToBpmVars mapping. In the bpm_orchestration4 quickstart [JBESB-QS] the XML came from the Seam DVD Store and the “SampleOrder.xml” looks like


<Order orderId="2" orderDate="Wed Nov 15 13:45:28 EST 2006" statusCode="0"
 netAmount="59.97" totalAmount="64.92" tax="4.95">
<Customer userName="user1" firstName="Rex" lastName="Myers" state="SD"/>
<OrderLines>
<OrderLine position="1" quantity="1">
<Product productId="364" title="Gandhi"
price="29.98"/>
</OrderLine>
<OrderLine position="2" quantity="1">
<Product productId="299" title="Lost Horizon" price="29.99"/>
</OrderLine>
</OrderLines>
</Order>

Note

Both ESB as well as jBPM deployments are hot. An extra feature of jBPM is that process deployments are versioned. Newly created process instances will use the latest version while existing process instances will finish using the process deployment on which they where started.

The org.jboss.soa.esb.services.persistence.MessageStore interface is defined as follows:


public interface MessageStore

{
    public MessageURIGenerator getMessageURIGenerator();
    public URI addMessage (Message message, String classification)
        throws MessageStoreException;
    public Message getMessage (URI uid)
        throws MessageStoreException;
    public void setUndelivered(URI uid)
        throws MessageStoreException;
    public void setDelivered(URI uid)
        throws MessageStoreException;
    public Map<URI, Message> getUndeliveredMessages(String classification)
        throws MessageStoreException;
    public Map<URI, Message> getAllMessages(String classification)
        throws MessageStoreException;
    public Message getMessage (URI uid, String classification)
        throws MessageStoreException;
    public int removeMessage (URI uid, String classification)
        throws MessageStoreException;
}

The MessageStore is responsible for reading and writing Messages upon request. Each Message must be uniquely identified within the context of the store and each MessageStore implementation uses a URI to accomplish this identification. This URI is used as the “key” for that message in the database.


Messages can be stored within the store based upon classification using addMessage. If the classification is not defined then it is up to the implementation of the MessageStore how it will store the Message. Furthermore, the classification is only a hint: implementations are free to ignore this field if necessary.

The default implementation of the MessageStore is provided by the org.jboss.internal.soa.esb.persistence.format.db.DBMessageStoreImpl class. The methods in this implementation make the required DB connections (using a pooled Database Manager DBConnectionManager).


To override the MessageStore implementation you should look at the MessageActionGuide and the MessagePersister Action.

To configure your Message Store, you can change and override the default service implementation through the following settings found in the jbossesb-properties.xml:



<properties name="dbstore">
  <!--  connection manager type -->
  <property name="org.jboss.soa.esb.persistence.db.conn.manager" value=
"org.jboss.internal.soa.esb.persistence.manager.StandaloneConnectionManager"/>
    <!-- this property is only used for the j2ee connection manager -->
    <property name="org.jboss.soa.esb.persistence.db.datasource.name"   
      value="java:/JBossesbDS"/>
    <!-- standalone connection pooling settings -->
    <!--  mysql
    <property name="org.jboss.soa.esb.persistence.db.connection.url"    
      value="jdbc:mysql://localhost/jbossesb"/>
    <property name="org.jboss.soa.esb.persistence.db.jdbc.driver"       
      value="com.mysql.jdbc.Driver"/>
    <property name="org.jboss.soa.esb.persistence.db.user"              
      value="kstam"/> -->
    <!--  postgres 
    <property name="org.jboss.soa.esb.persistence.db.connection.url"    
      value="jdbc:postgresql://localhost/jbossesb"/>
    <property name="org.jboss.soa.esb.persistence.db.jdbc.driver"       
      value="org.postgresql.Driver"/>
    <property name="org.jboss.soa.esb.persistence.db.user"              
      value="postgres"/>
    <property name="org.jboss.soa.esb.persistence.db.pwd"               
      value="postgres"/> -->
    <!-- hsqldb -->
    <property name="org.jboss.soa.esb.persistence.db.connection.url"    
      value="jdbc:hsqldb:hsql://localhost:9001/jbossesb"/>
    <property name="org.jboss.soa.esb.persistence.db.jdbc.driver"       
      value="org.hsqldb.jdbcDriver"/>
    <property name="org.jboss.soa.esb.persistence.db.user" value="sa"/>
    <property name="org.jboss.soa.esb.persistence.db.pwd" value=""/>    
    <property name="org.jboss.soa.esb.persistence.db.pool.initial.size" 
      value="2"/>
    <property name="org.jboss.soa.esb.persistence.db.pool.min.size"     
      value="2"/>
    <property name="org.jboss.soa.esb.persistence.db.pool.max.size"     
      value="5"/>
    <!--table managed by pool to test for valid connections
        created by pool automatically -->
    <property name="org.jboss.soa.esb.persistence.db.pool.test.table"   
      value="pooltest"/>        
    <property name="org.jboss.soa.esb.persistence.db.pool.timeout.millis"
      value="5000"/> 
</properties>    

The section in the property file called “dbstore” has all the settings required by the database implementation of the message store. The standard settings, like URL, db user, password, pool sizes can all be modified here.


The scripts for the required database schema, are again, very simple. They can be found under lib/jbossesb.esb/message-store-sql/<db_type>/create_database.sql of your JBossESB installation. 

The structure of the table can be seen from the sample SQL:



CREATE TABLE message
(
   uuid varchar(128) NOT NULL,
   type varchar(128) NOT NULL,
   message text(4000) NOT NULL,
   delivered varchar(10) NOT NULL,
   classification varchar(10),
   PRIMARY KEY (`uuid`)
);

The uuid column is used to store a unique key for this message, in the format of a standard URI. A key for a message would look like:



urn:jboss:esb:message:UID: + UUID.randomUUID()_

This logic uses the new UUID random number generator in jdk 1.5. the type will be the type of the stored message. JBossESB ships with JBOSS_XML and JAVA_SERIALIZED currently.


The “message” column will contain the actual message content.

The supplied database message store implementation works by invoking a connection manager to your configured database. Supplied with JBoss ESB is a standalone connection manager, and another for using a JNDI datasource.

To configure the database connection manager, you need to provide the connection manager implementation in the jbossesb-properties.xml. The properties that you would need to change are:


<!--  connection manager type -->
<property name="org.jboss.soa.esb.persistence.db.conn.manager" 
  value="org.jboss.internal.soa.esb.persistence.format.db.Standalone
ConnectionManager"/>
<!--  property name="org.jboss.soa.esb.persistence.db.conn.manager" 
value="org.jboss.soa.esb.persistence.manager.J2eeConnectionManager"/ -->
<!-- this property is only used for the j2ee connection manager -->
<property name="org.jboss.soa.esb.persistence.db.datasource.name" 
  value="java:/JBossesbDS"/>

The two supplied connection managers for managing the database pool are

The Standalone manager uses C3PO to manage the connection pooling logic, and the J2eeConnectionManager uses a datasource to manage it's connection pool. This is intended for use when deploying your ESB endpoints inside a container such as JBoss AS or Tomcat, etc. You can plug in your own connection pool manager by implementing the interface:

Once you have implemented this interface, you update the properties file with your new class, and the connection manager factory will now use your implementation.

The Security Service is configured along with everything else in jbossesb-properties.xml:


<properties name="security"> 
<property name="org.jboss.soa.esb.services.security.implementationClass"
value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>

<property name="org.jboss.soa.esb.services.security.callbackHandler" 
value= 
"org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
        
<property name="org.jboss.soa.esb.services.security.sealAlgorithm" 
value="TripleDES"/> 

<property name="org.jboss.soa.esb.services.security.sealKeySize" 
value="168"/>

<property name="org.jboss.soa.esb.services.security.contextTimeout" 
value="30000"/>

<property name= 
"org.jboss.soa.esb.services.security.contextPropagatorImplemtationClass" 
value= 
"org.jboss.internal.soa.esb.services.security.JBossASContextPropagator"/>
        
<property name="org.jboss.soa.esb.services.security.publicKeystore" 
value="/publicKeyStore"/> 


<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" 
value="testKeystorePassword"/> 

<property name="org.jboss.soa.esb.services.security.publicKeyAlias" 
value="testAlias"/> 

<property name="org.jboss.soa.esb.services.security.publicKeyPassword" 
value="testPassword"/> 

<property name="org.jboss.soa.esb.services.security.publicKeyTransformation" 
value="RSA/ECB/PKCS1Padding"/> 

</properties> 


Table 9.1. jbossesb-properties.xml Security Settings

PropertyDescriptionRequired?
org.jboss.soa.esb.services.security.implementationClass

This is the concrete SecurityService implementation that should be used. Required. Default is JaasSecurityService.

Yes

org.jboss.soa.esb.services.security.callbackHandler

A default CallbackHandler implementation when a JAAS based SecurityService is being used. See “Customizing security” for more information about the callbackHandler property.

No

org.jboss.soa.esb.services.security.sealAlgorithm

The algorithm to use for sealing the SecurityContext.

No

org.jboss.soa.esb.services.security.sealKeySize

The size of the secret/symmetric key used to encrypt/decrypt the SecurityContext.

No

org.jboss.soa.esb.services.security.contextTimeout

The amount of time in milliseconds that a security context is valid for. This is a global setting that may be overridden on a per service basis by specifying this same property name on the security element in jboss-esb.xml.

No

org.jboss.soa.esb.services.security.contextPropagatorImplementationClass

Configures a global SecurityContextPropagator. For more details on the SecurityContextPropagator please refer to the “Security Context Propagation”.

No

org.jboss.soa.esb.services.security.publicKeystore

Path to the keystore that holds a keys used for encrypting and decrypting data external to the ESB. This is used to encrypt the AuthenticationRequest.

No

org.jboss.soa.esb.services.security.publicKeystorePassword

Password to the public keystore.

No

org.jboss.soa.esb.services.security.publicKeyAlias

Alias to use.

No

org.jboss.soa.esb.services.security.publicKeyPassword

Password for the alias if one was specified upon creation.

No

org.jboss.soa.esb.services.security.publicKeyPassword

Cipher transformation in the format: “algorithm/mode/padding”. If not specified this will default to the keys algorithm.

No


The JAAS login modules are configured in the way you would except using the login-config.xml file located in the conf directory of your JBoss Application Server. So you can use the ones that come pre-configured but also add your own login modules.

Warning

By default JBossESB ships with an example keystore which should not be used in production. It is only provided as a sample to help users get security working “out of the box”. The sample keystore can be updated with custom generate key pairs.

Security is configured per-service. A service in JBossESB can be declared as being secured and that it requires authentication. Services are configured by adding a “security” element to the service in jbossesb.xml:


<service category="Security" name="SimpleListenerSecured"> 
   <security moduleName="messaging" runAs="adminRole"
    rolesAllowed="adminRole, normalUsers"
    callbackHandler="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"> 
        <property name="property1" value="value1"/> 
        <property name="property2" value="value2"/> 
   </security>
   ...
</service> 


Example of overriding global configuration settings:


<security moduleName="messaging" 
  runAs="adminRole" rolesAllowed="adminRole">

<property 
    name="org.jboss.soa.esb.services.security.contextTimeout" 
    value="50000"/> 
  
<property name=
"org.jboss.soa.esb.services.security.contextPropagatorImplementationClass"
    value="org.xyz.CustomSecurityContextPropagator" /> 

</security> 

To authenticate a caller, security information needs to be provided. If the call to the service is coming through a gateway, then the gateway will extract the required information from the transport that the gateway works with. For a web service call this would entail extracting either the UsernameToken or the BinarySecurityToken from the security element in the SOAP header.

When a service needs to call another services and that service requires authentication, another authentication process will be performed. So having a chain of services that are all configured for authentication will cause multiple authentications to be performed. To minimize such overhead the ESB will store an encrypted SecurityContext which will be propagated with the ESB Message object between services. If the ESB detects that a Message has a SecurityContext, it checks that the SecurityContext is still valid, and if so, re-authentication is not performed. Note that the SecurityContext is only valid on a single ESB node. If the message is routed to a different ESB node, re-authentication will be required.

This section lists the login modules provided with JBossESB. Please note that all login modules available with JBoss AS are available as well and custom login modules should be easy to add.

This login module performs authentication by verifiying that a certificate passed with the call to the ESB, can be verified against a certificate in a local keystore.

Upon successful authentication the certificates Common Name(CN) will be used to create a principal. If role mapping is in use then it is the CN that will be used in the role mapping. See “Role Mapping” for details on the role mapping functionality.


<security moduleName="CertLogin" rolesAllowed="worker"
  callbackHandler="org.jboss.soa.esb.services.security.auth.loginUserPass
CallbackHandler">
  <property name="alias" value="certtest"/>
</security>

Example of fragment from login-config.xml


<application-policy name="CertLogin">
<authentication>
  <login-module
code="org.jboss.soa.esb.services.security.auth.login.CertificateLoginModule"
flag = "required" >
  <module-option name="keyStoreURL">
    file://pathToKeyStore
  </module-option>
  <module-option name="keyStorePassword">storepassword</module-option>
  <module-option name="rolesPropertiesFile">
    file://pathToRolesFile
  </module-option>
  </login-module>
</authentication>
</application-policy>

Configuration files in JBossESB sometimes require passwords which up until now have been specified in clear text in the configuration files. This is a security risk and something that should be avoided. In JBossESB you have the ability to specify a path to a file that contains an encrypted password wherever a password is required.

Revision History
Revision 1Fri Jul 16 2010David Le Sage, Darrin Mison
Initial conversion from OpenOffice ODT files.