Download code samples for this article
One of the biggest problems we have is the need to integrate the different business systems that currently exist. We need to automate business transaction with partners, and to orchestrate business workflow with suppliers. The Java Business Integration (JBI) 1.0 specification, JSR 208, details some solutions. Targeted mainly (at the current time) for software engine developers, JSR 208 describes a set of Java APIs to interact with an implementation of a Java-based Enterprise Service Bus (ESB). This ESB must provide for the integration of disparate service components, enabling them to communicate with their consumers or clients through a myriad of communications modules.
ServiceMix is one of the very first working ESBs that includes support for all of the JBI 1.0 APIs, enabling you to explore and evaluate the potential benefits of an Enterprise Service Bus.
This article provides an introduction to ESB/JBI, the problems it attempts to solve, and describes the typical architecture. You will also learn about ServiceMix, and the components that it provides. A hands-on example will guide you through the installation and operation of the ServiceMix ESB. You will even code a couple of ESB components yourself.
Enterprise application integration
In Figure 1, which shows the typical scenario found in many modern day enterprise networks, services in the enterprise are being exposed to partners for automated business transactions.
Figure 1: EAI/B2B/B2C – Connecting to your suppliers, partners, and customers
Business partners, in turn, may expose services that the enterprise may consume (for example, referrals and workflow). In addition, suppliers’ systems are also connected, and business-to-business (B2B) features are being exposed to support automated interaction (for example, inventory check and ordering). Meanwhile, business-to-consumer technology is used to automate interactions with customers (for example, on-line ordering and product information).
In an ideal world, one would only need to connect the systems of the partners, suppliers, and customers, and the integration job would be completed. Unfortunately, however, as illustrated in Figure 2, the real world situation differs significantly. Even if all the systems from suppliers, partners, and customers use a common protocol (which is rare enough already), there is still a major issue with trust and security.
Figure 2: B2B networks in the real world where security threats limit interconnections
B2B integration in the real world
In Figure 2, it is evident that only the services related to suppliers should be available to your suppliers – and nothing else. The situation is the same with partners, and even customers. For simplicity, the rest of this article will only focus on the B2B connections. Typically, a firewall is used to block out all non-intended access, and hopefully isolates potential hackers. Increasingly, web services technology is used to expose “just enough” features to each audience. To implement the B2B functionality, many enterprises outsource EAI to global service firms. An alternative to outsourcing B2B is to attack the problem in-house. At the core, it is all about:- exposing services for external access
- consuming remote services
- accommodating different hardware/software platforms
- accommodating different access communications protocols and media
- doing it all securely
- preserving existing software assets by re-purposing legacy systems for modern access
- saving effort
- conserving budget
Any component, any protocol, anytime
Figure 3 explores the problem in a little more detail.
Figure 3: Mix and match of communications and business components in EAI/B2B
Architecturally, you have providers of services and you have consumer of services. Each of these may already have very specific interfacing and communication requirement.
To solve the problem depicted in Figure 3, one can certainly write custom adapter code for each pair of consumers and services that need to work together. However, if one seriously considers the scope of such an undertaking – especially factoring in the ever-increasing complexity of coping with a constantly changing set of partners and suppliers – the effort is obviously daunting.
When you are attempting to do it yourself, in-house, simplicity is of the utmost importance. Simple solutions are easier to convey to the implementation teams, can be significantly more resilient to change and modifications in requirements, and are easier to maintain in the long term. For solving the B2B problem, the notion of an Enterprise Service Bus (ESB) becomes a very attractive simple solution. Figure 4 depicts the high level idea of an ESB.
Figure 4: High level view of a JSR-208 ESB
Catching the Enterprise Service Bus
While high level, the ESB depicted in Figure 4 is quite specific. In fact, it is the core subject matter of JSR-208, a specification called Java Business Integration 1.0 (JBI 1.0). It is specified as a set of Java based APIs and component packaging conventions that all JBI compliant ESB implementations must follow. The JBI 1.0 APIs attempt to ensure that Java components developed can be deployed and executed across different vendors’ ESB implementations.SE versus BC
Core to Figure 4 is the idea of having two types of components that can plug into the bus – Service Engine and Protocol/Communication Bindings Components.A Service Engine (SE) is a component that encapsulates chunks of business logic, processing, or transformation functionality. It can represent a component that consumes services, or it can be a component that provides a service on the bus (that is, it can be a consumer or a provider). For example, a simple component may be created to look up employee information in the enterprise directory service, another one may transform XML data to HTML format to display product information.
A Binding Component (BC) isolates one type of communication and/or protocol interaction with systems external to the ESB. For example, a BC may encapsulate communications with legacy system that use proprietary protocol; while another BC may use messaging (via JMS) as a communications channel to external system.
By cleanly and clearly separating the business logic from the communications mechanism, flexible deployment-time “wiring” is possible – enabling encapsulated business logic code to be re-purposed, and accessed by new interconnection technology.
How components talk with one another over the ESB
All plug-in components on the ESB, regardless of type (SE or BC), and regardless of role (consumer or provider), all communicate in the same way.All components on the ESB communicate with one another by passing messages.
The components do not call one another’s methods or operations, they do not connect in client-server style with one another. This is a very important difference between ESB/JBI-based technology and other multi-platform interoperable APIs (CORBA, web services, etc).
In fact, the components never communicate with one another directly. They talk only to the ESB that they plug into. In this way, all of the components are extremely loosely coupled. It is this loosely coupled nature that gives an ESB solution such flexibility in dynamic re-configuration and re-purposing of components or subsystems.
This opens up two immediate questions:
- What format are the messages in?
- How does the message get from Component 1 to Component 2?
- Standards-based XML format.
- The ESB itself is responsible for getting the message between components.
Message normalization and denormalization
JSR-208 specifies that the message format used should be compliant with the W3C’s Web Services Description Language (WSDL) 2.0 or 1.1. To implement full decoupling between SEs and BCs, the messages must first be “normalized” before they are passed into the ESB (see Figure 5).
Figure 5: Components communicate via ESB using normalized messages
The ESB will only work with normalized messages, i.e. ones with protocol specificity removed. This means that you cannot tell, from examining the message, the connection or protocol over which it was sent.
A component must normalize any message before sending it to the ESB. Similarly, if a BC needs to send a message to an external system (outside of the ESB), the message must be denormalized before further routing or use. Denormalization puts back communications protocol-dependent frames, headers, and other information. This is the reason why an ESB is often also called a NMR or Normalized Message Router.
ServiceMix – a JBI 1.0 ESB you can deploy today
You can download and start working with your own JBI 1.0 ESB today.ServiceMix is open source and Apache 2.0 licensed. This means you don’t need to worry about its use in production projects. Download the latest binary release by following the Download link on the left. At the time of writing, the latest binary release available is 1.0.1. You will need JDK 1.4.2 or later installed and running before ServiceMix will work. You should also have Ant 1.5.4 or later installed – the example will require it.
Built-in Service Engine components in ServiceMix
To be useful, an ESB must come with a variety of pre-built components. ServiceMix comes with an ever-increasing array of pre-built components, covering both SEs and BCs. The Service Engine components available include the ones listed in Table 1 (and more).Table 1. Pre-built Service Engine components in ServiceMix | |
Engines | Description |
Quartz | A component that works with the Quartz scheduling engine, allows you to set multiple scheduled service invocation using ServiceMix. |
Drool | A component for rules based routing of messages. Flexible XML schema based “domain specific language” can be used to specify rules. Based on Rete algorithm (used in Expert Systems). |
BPEL | Business Process Execution Language for Web Services. A standards-based language for the orchestration of components and work flow in business processes. |
Groovy | A component for very flexible implementation of services, transformers, and routing logic. The code can be written in the Groovy scripting language and interpreted by the component at runtime. |
XSLT based Transformation | A component for transforming incoming normalized messages according to a deployed XSLT template. |
Validation | A component providing schema validation of messages. |
Generic scripting | A component enabling any JSR 223 compliant scripting language to be plugged into ServiceMix. |
XSQL | A component supporting Oracle’s tool for transforming SQL query to XML or persisting XML to database. |
Built-in Binding Components in ServiceMix
There is also a rich set of protocol support Binding Components that comes with ServiceMix, some of which are listed in Table 2. Of course, more are being added with each new version.Table 2. Pre-built Binding Components in ServiceMix | |
Binding | Description |
A component that allows you to send messages via email, implemented using a Spring framework component and JavaMail. | |
HTTP | Acceptsincoming messages via HTTP. This also includes an HTTP invoker component that can send messages via HTTP. |
FTP | Sends messages to an FTP server as files. Also a component to poll an FTP server for incoming file/messages. |
JMS | Sends and receives messages via JMS. |
JCA | Implements the required support framework of JCA 1.5 (Java Connector Architecture). This component allows compatible connector (typically JMS connector at this time) to run with ServiceMix applications. This component can provide a high performance interface to JMS brokers. |
RSS | A component for interfacing with RSS feeds and clients. Can poll feeds and generate messages or transform messages as outgoing RSS. |
Jabber | A component for communications via the Jabber P2P network with the XMPP protocol. You can send and receive messages from the Jabber network, and the component even supports the group chat protocol. |
VFS | A component implementing access to and from file systems (including OS file systems, jars and zips, Samba (CIFS), etc). |
SAAJ | Invokes web services using SOAP with Attachments and Apache AXIS. |
XFire | Supports the XFire lightweight SOAP stack – allowing POJOs to be bound as web services. |
Putting ServiceMix to work
Time to put ServiceMix to work. The example scenario is representative of several B2B interactions that you may encounter in real life, but applied on a micro and personal scale.Consider:
- Your partner – an investment counsellor who is also your stock broker
- Your supplier – a stock quote service supplying you with stock quote information
- wire up ServiceMix components to poll your supplier, using HTTP, for stock quotes every 15 seconds
- wire up a custom ServiceMix Service Engine to check the stock price; if it is over $3, send an email to your partner to congratulate him; if it is under $0.50, send an email to your partner to fire him
Intalling ServiceMix
To install ServiceMix, you only need to unarchive the ZIP file. If you look at the <ServiceMix installation directory>/bin directory, you will see the servicemix.bat file. The general usage is:servicemix <ESB configuration XML file>Where <ESB configuration XML file> is a descriptor configuring the components that you will be deploying to the ESB.
NOTE: JSR-208 specifies two JAR file-based deployable archive packages called Service Unit (SU) and Service Assembly (SA). These comprise binary code plus standard descriptors, in a manner similar to WAR and EAR packaging in J2EE. JSR-208 also mandates a set of Ant tasks to automate deployment, and JMX support for management of the JBI 1.0 compliant ESB during runtime. These topics are out of the scope of this article, please read JSR-208 if you are interested in more details.
While the SU and SA packaging are part of JBI 1.0 and fully supported by ServiceMix, they are tedious to perform during experimentation and development without IDE support. This example uses a ServiceMix startup and deployment scheme that allows for rapid iteration during development.
The code distribution for this article should be unarchived to a vsjmix directory under the <ServiceMix installation>/examples directory.
The configuration file in this example is called vsjmix.xml. Taking a look at this file, each and every component used is configured here. First, the Quartz scheduler component is configured to trigger every 15 seconds. The vsjmix.xml code is shown here, with the Quartz component timing configuration highlighted. A repeatCount attribute value of -1 means to repeat indefinitely:
<beans xmlns:my=”http://servicemix.org/demo/”> <container id=”jbi”> <property name=”rootDir” value=”../../wdir”/> <property name=”useMBeanServer” value=”true”/> <property name=”createMBeanServer” value=”true”/> <property name=”installationDirPath” value=”../../install”/> <property name=”monitorInstallationDirectory” value=”true”/> <property name=”dumpStats” value=”true”/> <property name=”statsInterval” value=”10”/> <components> <component id=”timer” service=”my:timer” class=”org.servicemix.components.quartz.QuartzComponent” destinationService=”my:httpGetData”> <property name=”triggers”> <map> <entry> <key> <bean class=”org.quartz.SimpleTrigger”> <property name=”repeatInterval” value=”15000”/> <property name=”repeatCount” value=”-1”/> </bean> </key> <bean class=”org.quartz.JobDetail”> <property name=”name” value=”My Example Job”/> <property name=”group” value=”ServiceMix”/> </bean> </entry> </map> </property> </component>If you are familiar with the Spring Framework, you should feel right at home with this sort of dynamic component configuration. This type of deploy-time component configuration and wiring is becoming very popular due to its flexibility.
In the listing above, notice the highlighted destinationService attribute. This specifies the ServiceMix component that the Quartz trigger will send the message to. This component is declared in vsjmix.xml as:
<component id=”httpGetData” service=”my:httpGetData” class=”org.servicemix. components.http.HttpInvoker” destinationService= ”my:receiver”> <property name=”url” value=”http://localhost:8080/”/> </component>The above code configures ServiceMix’s HttpInvoker component to invoke the stock quote URL: http://localhost:8080/ and then grab the returned data and send it as a message to the destinationService.
As a result of configuring and deploying these two components on the ESB, Quartz will trigger every 15 seconds, causing the HttpInvoker to hit the stock quote URL, packaging and sending the quote value to a component configured as my:receiver.
This my:receive component is configured in vsjmix.xml as:
<component id=”receiver” service=”my:receiver” class=”MyReceiver” destinationService=”my:mailSender” />This is the first custom-coded ServiceMix component in this example. It is a transformation component, participating in an In-out Message Exchange Pattern (MEP). MEPs are pre-defined message-based interactions between a component and the ESB. You can think of them as finite state machines used to clock data onto and off the bus. JBI 1.0 defines the following four MEPs:
- In-Only, similar to a one-way call, or call-and-forget; the sender is not interested in further status
- Robust In-Only, a one-way call, but with returned fault if the error occurs during send
- In-Out, a classic request response interaction, the output message is replaced by a fault if the exchange is not successful
- In Optional-Out, a two-way exchange where the response is optional, but the sender is obliged to report status or fault
import java.io.BufferedReader;
import java.io.IOException;
...
public class MyReceiver extends TransformComponentSupport implements
MessageExchangeListener {
protected boolean transform(MessageExchange exchange, NormalizedMessage
message, NormalizedMessage outmsg) throws MessagingException {
StringSource src = (StringSource) getBody(message);
double currentQuote = getQuote(src);
if (currentQuote > 2) {
sendEmail(outmsg, “buyer@valuedcust”, “[email protected]”,
“Excellent!”, “You are the greatest broker in the world!”);
}
else if (currentQuote < 0.5) sendEmail(outmsg, “buyer@valuedcust”,
“[email protected]”, “You’ve gotta be kidding!”,
“You are a disgrace to your profession. You are fired!!”);
done(exchange);
return true;
}
private double getQuote(StringSource src) {
String msgBody = “”;
double retval = 0.0;
BufferedReader rdr = new BufferedReader( src.getReader());
String content = “”;
String line = “”;
try {
while ((line = rdr.readLine())!= null) { content += line; }
} catch ( IOException ex) {}
finally { try { rdr.close(); } catch(IOException ex) {} }
String startTag = “<quote>”;
String endTag = “</quote>”;
int idx = content.indexOf(startTag);
int endIdx = content.indexOf(endTag);
if ((idx != -1) && (endIdx != -1) && (endIdx > idx)) {
String val = content.substring(idx + startTag.length() , endIdx);
retval = Double.valueOf(val).doubleValue();
}
return retval;
}
private void sendEmail(NormalizedMessage message, String from, String to,
String subject, String text) throws MessagingException {
message.setProperty(“org.servicemix.email.to”, to);
message.setProperty(“org.servicemix.email.from”, from);
message.setProperty(“org.servicemix.email.subject”, subject);
message.setProperty(“org.servicemix.email.text”, text);
}
}
The highlighted code is where the business decision is made. This is an In-out MEP. Note how easy it is to write this code, with the help of TransformComponentSupport super class and the MessageExchange. The “in” message, sent from the HttpInvoker, is trivially parsed by getQuote() to obtain the quote value. The helper sendEmail() method sets up properties of the “out” message, this message will be passed to the email sending component via ServiceMix. The done(exchange) helper method completes the In-out MEP, and the “out” message is passed back to the ESB for the next stop in the route.
If you look back at the configuration of my:receiver, you will notice the destinationService is configured to be my:mailSender. In actual deployment, you can use ServicMix’s included email sender component. For this example, so that you can “see” the email sending, a simulated custom component is used. The configuration for my:receiver, in vsjmix.xml, is:
<component id=”mailSender” service=”my:mailSender” class=”MyMailer” />The code for this component is in MyMailer.java. This uses an In-Only MEP, and is especially simple to code.
import java.util.Set; ... public class MyMailer extends PojoSupport implements MessageExchangeListener { public void onMessageExchange(MessageExchange exchange) throws MessagingException { NormalizedMessage message = exchange.getMessage(“in”); System.out.println(“MAILER sending email...” + “\nFrom: “ + message.getProperty( “org.servicemix.email.from”) + “\nTo: “ + message.getProperty(“org.servicemix.email.to”) + “\nSubject: “ + message.getProperty( “org.servicemix.email.subject”) + “\n” + message.getProperty( “org.servicemix.email.text”)); done(exchange); } }The code simply prints a dump of the email to be sent. It extracts the information from the headers of the “in” message.
To try out your ESB, use the following command (assuming you are in the examples/vsjmix directory:
..\..\bin\servicemix vsjmix.xmlEvery fifteen seconds, you should see the following message from the my:mailSender component.
MAILER sending email... From: buyer@valuedcust To: [email protected] Subject: Excellent! You are the greatest broker in the world!The quote used by the server is in the file quote.txt. Modify this to $0.3, and you should see the email to rid you of your broker.
If you experiment and modify the code, you can recompile it using the supplied build.xml file. Just type ant at the command line.
Simulating a simple stock quote service using ServiceMix components
One question may come into your mind. Where did the quote server, located at localhost:8080, come from?Well, you could have set up your own web server to handle the quote. However, since we have a “rapid server construction kit” with the ServiceMix ESB – why not use it?
In fact, the “quote server” consists of ServiceMix’s HttpConnector (incoming) configured as:
<component id=”httpReceiver” service=”my:httpBinding” class=”org.servicemix.components.http.HttpConnector” destinationService=”my:sender”> <property name=”host” value=”localhost”/> <property name=”port” value=”8080”/> </component>This works with a customised component using In-out MEP, called MySender.java. This component is configured as:
<component id=”sender” service=”my:sender” class=”MySender”/>The code for MySender.java is reproduced below. It simply reads a file named “quote.txt” and sends the content as an “out” message through the In-out MEP, to the ESB.
import java.io.BufferedReader;
...
public class MySender extends PojoSupport implements MessageExchangeListener
{
public void onMessageExchange(MessageExchange exchange)
throws MessagingException {
NormalizedMessage message = exchange.createMessage();
exchange.setMessage(message, “out”);
message.setContent(new StringSource(getQuote(“quote.txt”,
“<quote>3.0</quote>”)));
done(exchange);
}
private String getQuote(String fileName, String def) {
BufferedReader br = null;
String retval = “”;
try {
br = new BufferedReader (new FileReader(fileName));
String line = “”;
while((line = br.readLine())!=null) retval += line;
}
catch (Exception ex) {
// ignore, use default
}
finally {
if (br != null) try { br.close(); } catch (Exception ex) {}
}
if (retval.length() == 0) return def;
else return retval;
}
}
A versatile and truly usable ESB
Although not mandated by JBI 1.0, ServiceMix tries very hard to adapt ESB functionality to the varying requirements of modern developers/architects. In order to accomplish this, the ESB engine itself must be able to live and work in a variety of configuration scenarios.Figure 6 illustrates the different configurations that ServiceMix can operate under.
Figure 6: The three operation modes of the ServiceMix ESB
In this article, ServiceMix has mostly been operating in the standalone mode – allowing us to quickly start and stop our ESB for experimentation. But ServiceMix also supports embedded mode, where an application can embed the ServiceMix ESB and any required components. The application can then offer functionality based on the ESB SEs or BCs. In the third configuration, a ServiceMix WAR file is available with the download. This allows ServiceMix to run as a web application within a J2EE container. In fact, ServiceMix comes pre-integrated into the open source J2EE server – Geronimo.
Conclusions
JBI is designed from the ground up to simplify the organisation and integration of your enterprise’s software assets. ServiceMix is one of the very first implementations of an Enterprise Service Bus that fulfils the JBI vision.With ServiceMix, re-purposing of any compatible software component or service is as simple as changing a configuration file. Existing business logic components can be leveraged through a wide variety of communications protocol bindings, exposing them in a flexible yet secure manner to your partners, suppliers, or customers.
By basing the component level interchange on current web services standards, JBI and ServiceMix expedite adoption of the model by simplifying the construction of the software components for the ESB. This allows component developers to fully leverage the competitive, multi-vendor, rich tool support available today for the creation of web services.
Sing Li is a consultant, trainer and freelance writer specialising in Java, Windows NT and distributed object technologies. Li’s most recent publication is Early Adopter JXTA: Peer-to-Peer Computing with Java from Wrox Press.
Comments