An enterprise service bus (ESB) is a centralized, logical, architectural component that operates in a distributed, heterogeneous environment to facilitate the requirements of a highly scalable, fault-tolerant, service-messaging framework. An ESB acts as an open and implementation-independent service messaging and interfacing model that isolates application code from the specifics of routing services and transport protocols, and allows substitution of service implementations as needed.
An ESB acts as a shared messaging layer for connecting applications and other services throughout an enterprise computing infrastructure. It supplements its core asynchronous messaging backbone with intelligent transformation and routing to ensure messages are passed reliably. Services participate in the ESB using either Web services messaging standards or Java Message Service (JMS). Originally defined by analysts at Gartner, ESB is increasingly seen as a core component in a service-oriented infrastructure.
In this article, I discuss the open source ESB ServiceMix and its relationship to the Java Business Integration specification.
Minimum requirements of ESB message delivery
The minimum requirements of an ESB, as a message delivery system, are often referred to by the acronym TRANS, which defines an ESB as a software entity that does the following:
- Transforms messages from one format to another to accommodate the requirements of registered service providers.
- Routes messages to registered services while providing quality-of-service and service-level features.
- Augments message content with information, such as additional metadata, about the message requester. Augments the message protocol to meet service provider requirements.
- Notifies registered message listeners about specific message requests.
- Secures delivery of messages by enforcing authentication, authorization, nonrepudiation, confidentiality, etc.
Introducing Java Business Integration (JBI)
The Java Business Integration (JBI) specification and API defines a platform for building enterprise-class ESBs using a pluggable, service-based design. JBI builds on the TRANS foundation with normalized messages and component-based interactions.
JBI is a specification and an API for a normalized messaging service along with a component framework and management model for deploying integration services such as routing engines, rule engines, and transformation services. A JBI-based design specifies a standards-based pluggable architecture with a JVM-based runtime component called the normalized message router (NMR).
The high-level interactions of JBI can be seen in Figure 1 below.
JBI embodies a messaging model based on Web Services Description Language (WSDL) for easy mapping to Web services, HTTP, email, and JMS. JBI integrates with legacy systems, binary transports, document-oriented transports, and RPC (remote procedure call) systems.
Figure 1's binding components deal with protocol-oriented relationships and components. And service-engine components in JBI support content-based routing, orchestration, rules, transformations, custom augmentation, etc.
JBI uses a "normalized" message—consisting of a payload, optional attachments, and metadata—for interaction between consumers and providers. Message normalization is the process of mapping context-specific data to a context-neutral abstraction to transport data in a standard format. All messages handled by the NMR are normalized.
A normalized message consists of three main parts:
- Message content, also referred to as "payload," which is an XML document that conforms to an abstract WSDL message type with no protocol encoding or formatting.
- Message properties or metadata that hold extra data associated with the message. This metadata can include security information, transaction-context information, component-specific information, etc. Message properties form the first part of what is referred to as the message context.
- Message attachments referenced by the payload, contained within a data handler used to manipulate the attachment's contents. Attachments can be non-XML data. Attachments form the second part of the message context.
Normalized message router
The JBI message exchange depends on the NMR to route message exchange objects between service consumers and providers. The NMR performs such message delivery with varying qualities of service, depending on application needs and the nature of the messages being delivered.
An NMR is not embodied by any concrete object. It is abstracted as a set of APIs, SPIs (service provider interfaces), and components. The NMR APIs include:
- JBI Message API
- JBI Service API
- JBI Message Exchange Factory API
- Service Description SPI
- Message Exchange Patterns API
- Endpoint Reference API
A JBI delivery channel represents a bidirectional communication pipe used by binding components and service engines to transport messages across the NMR. The
javax.jbi.messaging.DeliveryChannel interface forms the API contract between service consumers, service providers, and the NMR.
A service consumer uses its delivery channel to initiate service invocations, while a service provider uses its delivery channel to receive invocations. A component that functions as both consumer and provider uses the same delivery channel for both roles. Therefore implementations of
DeliveryChannel must support concurrent use of a given instance from multiple threads.
The JBI component framework provides a pluggable interface that allows binding components and service engines to interact with the JBI environment. The framework provides the interface to all of the JBI services.
JBI supports two kinds of components, service engines and binding components. Components interact with JBI in two ways:
- SPIs: Interfaces implemented by a binding or engine
- APIs: Interfaces exposed to bindings or engines by the framework
Service engines are the business-logic components in a JBI system and can serve as service providers/consumers. Service engines orchestrate service consumption and requirements. Service engines can also provide services such as data transformation, sophisticated routing, and message coordination facilities.
Binding components are used to send and receive messages across specific protocols and transports. They uncouple the JBI environment from protocol specifics by marshalling and unmarshalling messages to and from protocol-specific data formats, allowing the JBI environment to process only normalized messages.
Normalized message exchange
JBI's principal purpose is to route normalized message exchanges from one component to another. Messages are delivered in a normalized form.
Binding components must convert protocol/transport-specific messages to a normalized form. Binding components and service engines interact with the NMR via a delivery channel, which provides a bidirectional delivery mechanism for messages.
An external service consumer sends a service request across a specific protocol and transport to a binding component. The binding component converts the request to a normalized message. The binding component then creates a message packet called a message exchange (ME) and sends it across the binding component's delivery channel to the NMR for delivery to a service provider.
After receiving a message, the consuming service engine or binding component creates a normalized message, putting it into a new
MessageExchange instance, and sends it to the target
ServiceEndpoint instance. After accepting the ME, the
ServiceEndpoint component de-normalizes the message into protocol and transport format, and sends the message along to the external service provider.
Component-specific artifacts deployed to an installed engine or binding are referred to as service units. Service units are grouped into an aggregate deployment file called a service assembly. This file includes a deployment descriptor that indicates the component into which each service unit is to be deployed.
Service units contain:
- Metadata: JBI descriptor for services consumed/produced
- Artifacts: Generally XML (possibly binary, whatever the target binding component or service engine needs)
ServiceMix is an ESB based on JBI. Released under the Apache license, it is an open source ESB and SOA toolkit built on JBI's semantics and APIs. The toolkit is lightweight and easily embeddable, has integrated Spring support, and can run inside a client or server, as a standalone ESB provider, or as a service within another ESB. You can use ServiceMix in a Java Standard Edition or Java Enterprise Edition application server. ServiceMix is completely integrated with JBoss and Apache Geronimo and lets you deploy JBI components and services directly into Geronimo.
Figure 2 illustrates the relationships between JBI and ServiceMix.
ServiceMix includes a complete JBI container that supports all parts of the JBI specification including:
- A normalized message service and router
- JBI management beans (MBeans)
- Ant tasks for management and installation of components
- Full support for the JBI deployment units with hot-deployment of JBI components
ServiceMix also includes the following components and services:
- Service components
- Rules-based routing via the Drools rule engine
- A client API for working with JBI components and services
- An implementation of Web Services Notification
- Business Process Execution Language (BPEL) support for Web Services BPEL via PXE (preboot execution environment)
- Support for caching service invocations using a
Mapcache or a
- Support for the Java Connector Architecture
- Timer integration via the Quartz library
- Scripting support, allowing any Java Specification Request 223-compliant scripting engine to be used to create a component, perform a transformation, or act as an expression language
- Transformation using Extensible Stylesheet Language Transformations
- Schema validation of documents using the Java API for XML Processing 1.3 and XML Schema or RelaxNG
- XSQL for working with SQL and XML via Oracle's XSQL library
- SOAP bindings
- Support for a SOAP stack based on the Streaming API for XML (StAX) via ActiveSOAP
- Support for the Java API for XML-based Web Services to make a Web services client invocation or host a Java-based Web service and expose it over multiple protocols
- Reflection to allow plain-old Java objects (POJOs) to be deployed in ServiceMix
- SOAP with Attachments API for Java and Apache Axis support
- Integration with POJOs via the XFire SOAP stack
- Integration with the Apache Web Service Invocation Framework (WSIF)
- Transport bindings
- Email support via JavaMail
- File-based components for writing messages to files and polling directories and sending files into the JBI
- FTP support via the Jakarta Commons Net library
- HTTP support for client-side and server-side processing
- Bindings to the Jabber network via the Extensible Messaging and Presence Protocol
- JMS support via ActiveMQ
- RSS support via the Rome library for accessing and processing RSS feeds
- VFS (virtual filesystem switch) via the Jakarta Commons Net library, which provides access to file systems, jar/zip/bzip2 temporary files, World Wide Web Distributed Authoring and Versioning, Samba (Common Internet File System), HTTP, HTTPS, FTP, SFTP, and others
Most of the ServiceMix initialization processes, activation processes, and message-exchange processes, involve some form of communication and/or interaction with JBI-based components. The following sections illustrate these processes within the context of a simple message-exchange scenario.
Initializing the JBI container
Before the JBI container can be used, it must be initialized by calling its
init() method. This method instantiates vital system services and sets the values for the JMX (Java Management Extensions)
MBeanServer, transaction manager, etc.
The snippet in Listing 1 illustrates the code needed to initialize the JBI container.
Listing 1. JBI container initialization
protected JBIContainer jbiContainer = new JBIContainer(); jbiContainer.init();
init() method traverses through the following steps:
- Initialize the
org.servicemix.jbi.management.ManagementContextinstance and register it with the JMX MBean server. This object is the primary point of interaction for management tools, such as JMX managers.
- Initialize the
org.servicemix.jbi.container.EnvironmentContextinstance and register it with the JMX MBean server. This object creates the directory structure for the install files, deployment files, components, shared libraries, service assemblies, etc.
- Initialize the
org.servicemix.jbi.framework.Registryinstance. This object maintains endpoints and components.
- Initialize the
org.servicemix.jbi.nmr.Brokerinstance. This object manages the actual message queuing and dispatching with the help of an
Flowobject manages the broker's dispatch policies.
- Initialize the
org.servicemix.jbi.framework.FrameworkInstallationServiceimplementation instance. This object installs and uninstalls archives.
- Initialize the
org.servicemix.jbi.framework.DeploymentServiceinstance. This object deploys service assemblies and their associated service units.