A service-oriented architecture (SOA) is never established in a vacuum. In any real life situation, an existing IT environment must be taken into consideration, offering functionality -- and data -- that cannot simply be replaced by a set of new services. Hence, a key aspect of building an SOA is to decompose existing applications into smaller blocks (that is, the "services") that communicate over standard protocols and have well-defined interfaces. The advantage of this is that such environments are more flexible, without tight coupling between various parts of the overall system.
This concept of loosely coupled and platform independent services is further advanced by the use of an Enterprise Service Bus (ESB). Among other things, an ESB serves as the "glue" between services that use different data and message formats, network protocols, and programming languages. The ESB serves as a level of indirection between a service consumer and a service provider, enabling the deployment of mediations that apply quality of service to an interaction, or to perform required data transformations, to name just two examples.
In this series of articles, we will look at a concrete example of an ESB serving as such an intermediary. We will leverage the IBM WebSphere Enterprise Service Bus (WebSphere ESB) V6.0.1 product to connect service consumers and service providers, using JMS as the messaging mechanism. In this first article, we will take a brief look at the WebSphere ESB product and its tooling environment, namely WebSphere Integration Developer V6.0.1. Part 2 will describe the actual ESB scenario and explain how we build the service consumer and service provider, and then Part 3 will show how we build the mediation between the consumer and the provider that runs in WebSphere ESB. You will learn how to deploy and run the solution, and we will provide all of the code artifacts needed for you to do so.
The Enterprise Service Bus and Java Message Service
An SOA consists of service consumers and service providers that communicate with each other. They typically do so through an Enterprise Service Bus. Each service has a service definition that describes, among other things, the messages it accepts from consumers and, unless it is a "one-way" service, the messages it returns to its consumers. Thus, building an ESB has much to do with messaging. The ability to send and receive messages in a robust, fast, and reliable way has been a key requirement of IT systems for a long time, and the advent of the ESB does not change that at all; it just introduces additional requirements towards a solution -- for example, support for standards describing message formats, transactional exchanges between services, and so on.
At the same time, systems based on the Java J2EE platform usually utilize the Java Message Service (JMS) API for their messaging needs. Simply put, the JMS standard describes how to send messages from one application to another, potentially exploiting a transactional quality of service.
Given that many applications already use JMS, and given that the services within an SOA need a way to do messaging, it makes perfect sense to use JMS in the context of an ESB. Each ESB must be capable of receiving messages via JMS from a service consumer and forward them to the appropriate service provider, over JMS, or over a different protocol (like HTTP), and vice versa. Moreover, JMS defines several different types of messages that can be sent. For example, a Text message contains a string representation of a message; an Object message contains a serialized Java object; a Map message contains a map of key/value pairs and so forth. Web services typically use SOAP as their message format, but many applications leverage plain XML. Hence, an ESB must support a wide variety of network and message protocols. Figure 1 shows a number of protocol combinations that service consumers and service providers may support. Notice that the ESB acts as the intermediary between the two, enabling connectivity between any consumer and provider regardless of protocol.
Figure 1. Example message and network protocols in SOA
How to set up WebSphere ESB to support these different combinations is exactly what we will discuss in this series. First, though, let us look at the product itself and its main components.
WebSphere ESB V6.0.1
The WebSphere ESB product is part of the IBM SOA Foundation. Even though its version number may suggest that this product has been around for a long time, it was released for the first time at the end of 2005, and shares many components with other already existing members of the WebSphere product family. For example, it uses the J2EE-based IBM WebSphere Application Server as its core runtime. WebSphere Application Server offers a JMS implementation that is reused by WebSphere ESB. It also uses the recently announced Service Component Architecture (SCA) as its basic programming model, and it shares the SCA runtime with WebSphere Process Server.
Figure 2 shows an overview of WebSphere ESB and its base components.
Figure 2. WebSphere ESB overview
WebSphere ESB supports basic messaging via JMS, and can communicate with WebSphere MQ via the MQLink feature in WebSphere Application Server. Web services utilizing SOAP over HTTP and SOAP over JMS are plugged into the ESB, with support for many Web services standards and a UDDI registry provided through the application server. WebSphere ESB can be used not only from standard J2EE clients, but also offers client support for C/C++ and .Net®. Moreover, it provides connectivity to a large number of legacy environments through WebSphere Adapters.
WebSphere ESB and Service Component Architecture
We mentioned above that the programming model utilized by WebSphere ESB is based on SCA. SCA describes a complete service programming model, across a number of components that can all be described and accessed in the same way, namely as services. Such components can be BPEL processes, business rules, human tasks, or plain Java components, just to name some examples. WebSphere ESB introduces a new component type to the SCA model, namely mediation flow components. From the perspective of SCA, a mediation flow component is no different than any other service component, in that a mediation component:
- exists in a module (more specifically, it exists in a mediation module, which is how it is deployed into a server runtime).
- has an interface, described either in Java or in WSDL.
- is exposed to clients via exports, which can have multiple bindings for different protocols (we'll get back to this).
- has dependencies to other service components via imports, which also have bindings describing protocol details.
In one respect, the mediation flow programming model is unique; it enables binding-specific information about the service message being processed (typically header-type information) to be accessed and manipulated. For a detailed description of SCA and its programming model, and how to build and deploy components through it, see the Building SOA solutions with the Service Component Architecture article series. (For the remainder of this series, we will assume you have basic knowledge of SCA, simply so that we don't repeat things that have been sufficiently covered elsewhere.)
Mediation flow components provide a new kind of implementation for a service component, namely that of a mediation flow. A mediation flow is normally built using a visual flow editor, and describes how both request and response messages flow through a series of mediation primitives. These primitives can read and change messages, or route ("filter") them to different targets. While you can build your own custom mediation primitives, the product comes with a number of predefined ones for:
- XSLT transformation
- Message logging
- Message filtering
- Database access.
Figure 3 shows a mediation flow component implementation that uses a number of mediation primitives to implement a response flow.
Figure 3. A sample mediation flow
By the way, in Part 2 we will go through the steps required to create such a flow.
WebSphere ESB and service message objects
What we haven't discussed yet is how messages are handled when they are "in the bus." In other words, how is data represented that is sent into a mediation flow component? The answer is that each message will be transformed into a Service Message Object as soon as it arrives in the mediation flow component. Similarly, before it leaves the mediation flow component, it is transformed back into whatever format is required by the target of the message.
Service message objects are an extension to the Service Data Object (SDO) specification, which describes a way to access data in a source-independent way. Thus, it doesn't matter if the message came in over HTTP or JMS or any other protocol, and it doesn't matter if it is a SOAP message or plain text, it is always turned into a generic format that can be used by the actual mediation flow implementation (for example, a mediation primitive).
Therefore, SCA provides the programming model for invoking a mediation flow component, and SMO/SDO represent the actual messages that are handled in this component. Both work hand in hand.
SCA export and import bindings
As mentioned earlier, an SCA component uses imports and exports to communicate with the outside world (that is, with clients that use the component and with other services that the component's implementation uses). Translating this into the world of WebSphere ESB and its mediation flow component, you can think of an export as the inbound port of the ESB, and of an import as the outbound port.
Assume, for example, that you have an existing service consumer and an existing service provider which communicate via SOAP over HTTP. Now you want to insert a WebSphere ESB mediation into this connection so that you can easily log each message that goes across. You do this by creating a mediation flow component and giving it the same interface as the target service. Then, you create an import that points to the existing Web service by creating a Web services binding for the import, which refers to the WSDL of the target service, including its endpoint address. In other words, you have "bound" the import to the Web service. Similarly, you create a Web services binding for the export, which results in a new WSDL file being generated, with an endpoint that points to the mediation flow component. Finally, you deploy this component and tell the service consumer to use the new endpoint address. What happens is that messages are now directed into WebSphere ESB, routed through a series of mediation primitives, and then forwarded to the actual target Web service.
Remember that we mentioned that each message becomes an SMO in the bus? The Web services binding is the piece of logic that transforms the incoming SOAP/HTTP request message into a service message object, and the outbound Web services binding provides the reverse logic; that is, it transforms the outgoing SMO back into a SOAP/HTTP message. This all happens automatically. The runtime knows what the incoming message looks like, since it is a SOAP message fully described by a WSDL definition, and it can parse and handle it accordingly.
What happens, though, if a message comes in that does not follow a specific message protocol like SOAP? For example, if a JMS map message is sent to an export, we cannot use default bindings because we don't know what this map looks like. This is where custom bindings come into play. The conversion from the incoming message into an SMO must be provided to the runtime in the form of a Java class that executes the appropriate parsing logic and builds the correct SMO. The same happens again at the outbound side; that is, at the import. A custom binding implementation knows how to take the SMO and turn it into the correct format.
In Parts 2 and 3 of this series, we will look at a detailed example for a custom JMS binding, namely one that supports all five JMS message types, so we will revisit the topic of custom bindings again and show you how to deploy a custom binding into the runtime as part of a mediation module.
WebSphere Integration Developer V6.0.1
One of the goals of WebSphere ESB is to make it simpler to create mediations and insert them into the flow of messages across the enterprise. In part, this is achieved by leveraging the SCA programming model, which enables treating different types of services with one description and deployment mechanism. The SCA specification also describes a way to assemble these components into larger solutions. Moreover, we want to support composing mediation flow components out of fine-grained mediation primitives. All of these things are supported by WebSphere Integration Developer V6.0.1.
Above, we showed a picture of a mediation flow component implementation using a number of primitives. The tool also supports visually assembling mediation flow components, exports, and imports into mediation modules that can be deployed and installed into the runtime. For example, Figure 4 shows how the assembly editor is used to build a mediation module with a mediation flow component in it.
Figure 4. Mediation module containing a mediation flow
The article series mentioned earlier, Building SOA solutions with the Service Component Architecture, explores a detailed sample scenario using this tool. We will also go through building a mediation module in Part 3.
In this article, we described how an Enterprise Service Bus can be built using the WebSphere ESB product, which supports a variety of message and network protocols that can be used to connect to both existing and new services. One of these protocols is JMS.
WebSphere ESB is based on the new Service Component Architecture and utilizes Service Data Objects as its internal message format model. SCA defines the notion of bindings to make a service component available to clients and to let it communicate with other components. In the case of the five different JMS message types, we need to provide custom binding implementations so that any message format can be supported.
In the remaining two articles of this series, we will take you through an example that leverages WebSphere ESB to handle messages that are exchanged between a JMS client and a (JMS-based) message-driven bean. You will learn how to develop and deploy custom binding implementations, all using WebSphere Integration Developer as the tooling environment to build the solution.
The specification for the solution introduced in this series was written by Rob Phippen from the IBM Hursley development lab. The actual code was designed and developed by Chuan Feng Li, Min Li and Xin Peng Liu, all from the IBM China Software Development Lab in Bejing.
More articles in this series
- WebSphere ESB product information
- Enterprise Service Bus information
- Building SOA solutions with the Service Component Architecture
- Service Component Architecture (SCA)
- Introduction to Service Data Objects
- WebSphere ESB Information Center
- Service-oriented modeling and architecture
- SOA and Web Services
- Web Services Architectures and Best Practices
- Service Data Objects reference collection
- Redbook: Patterns: Service-Oriented Architecture and Web Services
- Redbook: Patterns: Implementing an SOA using an Enterprise Service Bus
- Redpaper: Patterns: Using Business Service Choreography In Conjunction With An Enterprise Service Bus