Plug into JBI with ServiceMix

This article was originally published in VSJ, which is now part of Developer Fusion.

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
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
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
Essentially, the selected solution must be interoperable with whatever access technology and protocols your partners or suppliers are using.

Any component, any protocol, anytime

Figure 3 explores the problem in a little more detail.

Figure 3
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
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:

  1. What format are the messages in?
  2. How does the message get from Component 1 to Component 2?
The quick answers are:
  1. Standards-based XML format.
  2. 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
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
Email 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
The example scenario is the following:
  • 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
Before looking at the configuration and component code, you need to install ServiceMix.

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:
  1. In-Only, similar to a one-way call, or call-and-forget; the sender is not interested in further status
  2. Robust In-Only, a one-way call, but with returned fault if the error occurs during send
  3. In-Out, a classic request response interaction, the output message is replaced by a fault if the exchange is not successful
  4. In Optional-Out, a two-way exchange where the response is optional, but the sender is obliged to report status or fault
See JSR-208 for more details on these JBI 1.0 MEPs. Custom ServiceMix components make use of objects called MessageExchange to handle MEPs. By using the MessageExchange object, the states of the MEP can be enforced. Helper methods also keep the code simple. The code for the my:receiver component is found in the MyReceiver.java source file, reproduced here:
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.xml
Every 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
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.

You might also like...

Comments

About the author

Sing Li United States

Sing Li has been writing software, and writing about software for twenty plus years. His specialities include scalable distributed computing systems and peer-to-peer technologies. He now spends ...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Linux is only free if your time has no value” - Jamie Zawinski