ServiceMix as an enterprise service bus

Use ServiceMix 2.0 as a service-oriented message routing framework

1 2 Page 2
Page 2 of 2

Starting the JBI container

Startup for the JBI container is instigated by a simple call to the start() method on the JBIContainer instance, as illustrated in Listing 2. This process starts all embedded components and services, such as the registry, the broker, the management context, the environment context, the installation service, and the deployment service. The start process for most components and services simply involves setting a flag that designates they are in a running state and starting any associated timed tasks.

Listing 2. JBI container startup

 jbiContainer.start();

Creating the support components

Objects that serve as producers and consumers of messages in the ServiceMix framework are often referred to as support components. These objects implement the javax.jbi.component.Component interface so the JBI container and associated components can operate on them in a standard fashion. These objects generally extend some form of Support class found in the org.servicemix.components.util package, such as ComponentSupport or PojoSupport, endowed with the default behavior needed to act as a JBI component, e.g., JMX functionality.

Support components typically use an instance of javax.jbi.component.ComponentContext to retrieve a DeliveryChannel component to create and handle the actual message exchange.

Note the class/interface hierarchy for the support components in Listing 3.

Listing 3. Support-component hierarchy

 // The PojoSupport class encapsulates a simple POJO-based component that
// Provides support for standard ServiceMix-managed components
public abstract class PojoSupport
   extends org.servicemix.jbi.management.BaseLifeCycle
   implements javax.jbi.component.ComponentLifeCycle
{
…
}
// The ComponentSupport class extends PojoSupport and provides the
// functionality of a standard JBI component
public abstract class ComponentSupport
   extends org.servicemix.components.util.PojoSupport
   implements javax.jbi.component.Component
{
…
}
// The SenderComponent class will act as a producer of ServiceMix messages
public class SenderComponent
   extends org.servicemix.components.util.ComponentSupport
   implements Sender
{
…
}
// The ReceiverComponent class will act as a consumer of ServiceMix messages
public class ReceiverComponent
   extends org.servicemix.components.util.ComponentSupport
   implements org.servicemix.MessageExchangeListener, Receiver
{
…
}

Activating the support components

Before a component can be used within the ServiceMix ESB, the component must be "activated" within the context of the ServiceMix JBI container. This involves:

  • Constructing an instance of the DeliveryChannel class. This instance will then be associated with it for subsequent message exchanges. DeliveryChannel is responsible for the following:
    • Receiving messages routed to the component
    • Sending asynchronous messages
    • Sending synchronous messages
  • Registering the component with an instance of the org.servicemix.jbi.framework.ComponentRegistry class. The result of this step is an instance of the org.servicemix.jbi.framework.ComponentConnector class. This object is used internally by ServiceMix to exchange messages.
  • Register the ComponentConnector instance created by the ComponentRegistry class with an instance of the org.servicemix.jbi.container.EnvironmentContext class. The EnvironmentContext class maintains the JBI execution environment (installation path, deployment path, service-unit directory, etc.) in which the component is running.
  • Calling the component's lifecycle init() method and then its start() method.
  • Wrapping the component's ComponentConnector instance as a JMX MBean and registering it with the JBI container's org.servicemix.jbi.management.ManagementContext MBeanServer instance.

Activating components involves interacting with the org.servicemix.jbi.container.JBIContainer class via the activateComponent() method. This method takes an instance of the org.servicemix.jbi.container.ActivationSpec class, which is used to build a valid JBI component. The ActivationSpec object is an instance of one of three different Java class types that will ultimately be activated. These types are:

  1. javax.jbi.component.Component
  2. javax.jbi.component.ComponentLifeCycle
  3. org.servicemix.MessageExchangeListener: An instance of this class is wrapped within an instance of org.servicemix.components.util.PojoLifecycleAdaptor or a subclass of org.servicemix.components.util.ComponentAdaptor, such as org.servicemix.components.util.ComponentAdaptorMEListener

The snippet in Listing 4 illustrates how to activate the sender and receiver components.

Listing 4. Activating the sending and receiving components

 // Activate the sending component
String senderComponentID = "sender";
org.servicemix.jbi.container.ActivationSpec senderActivationSpec =
   new org.servicemix.jbi.container.ActivationSpec(senderComponentID,
                                                   sender);
jbiContainer.activateComponent(senderActivationSpec);
// Activate the receiving component
String receiverComponentID = "receiver";
org.servicemix.jbi.container.ActivationSpec receverActivationSpec =
   new org.servicemix.jbi.container.ActivationSpec(receiverComponentID,
                                                   receiver)
jbiContainer.activateComponent(receverActivationSpec);

Send and receive messages with the support components

Sending messages in ServiceMix involves transmitting the message through a sender support component and receiving the message through a "listening" receiver support component.

A typical sender component:

  1. Retrieves an instance of javax.jbi.messaging.DeliveryChannel from its ComponentContext
  2. Retrieves an instance of javax.jbi.messaging.MessageExchangeFactory from the DeliveryChannel instance
  3. Uses the MessageExchangeFactory instance to create an implementation of javax.jbi.messaging.MessageExchange containing the message content
  4. Transmits the MessageExchange instance to the destination via the DeliveryChannel instance

The example in Listing 5 shows how to send a String-based XML message through a sender component:

Listing 5. Send a message with a sending component

 public void sendMessage(String xml)
{
   try
   {
      ComponentContext context = getContext();
      InOnly exchange =
         context.getDeliveryChannel().
            createExchangeFactory().createInOnlyExchange();
      NormalizedMessage message = exchange.createMessage();
      message.setContent(new StringSource(xml));
      if (resolver != null)
      {
         ServiceEndpoint destination =
            resolver.resolveEndpoint(getContext(),
                                     exchange,
                                     NullEndpointFilter.getInstance());
         exchange.setEndpoint(destination);
      }
      exchange.setInMessage(message);
      // Now, send the message exchange
      context.getDeliveryChannel().send(exchange);
   }
   catch (Exception e)
   {
      e.printStackTrace();
   }
}

An interested component can subscribe to message exchanges within the ServiceMix framework through numerous approaches. One simple mechanism allows the receiving component to implement the MessageExchangeListener interface and the sending component to set the receiving component as its org.servicemix.jbi.resolver.EndpointResolver component. With this in place, ServiceMix sends all messages from the sender to the receiver. The code sample in Listing 6 illustrates this process.

Listing 6. A simple EndPointResolver-based receive process

 public class ReceiverComponent
   extends ComponentSupport
   implements MessageExchangeListener, Receiver
{
...
   // Method for the MessageExchangeListener interface
   public void onMessageExchange(MessageExchange exchange)
      throws MessagingException
   {
      NormalizedMessage inMessage = exchange.getMessage("in");
      if (inMessage == null)
      {
         throw new MessagingException("Null in message delivered!");
      }
      System.out.println(inMessage);
   }
}
// Creating the receiver and sender components and setting the receiver
// component as the EndpointResolver object in the sender component
ReceiverComponent receiver = new ReceiverComponent();
SenderComponent sender = new SenderComponent();
sender.setResolver(new ServiceNameEndpointResolver(ReceiverComponent.QNAME));

Figure 3 illustrates the send/receive sequence of a simple message exchange in ServiceMix.

Figure 3. The send/receive sequence of a simple message in ServiceMix. Click on thumbnail to view full-sized image.

Installing and starting ServiceMix on Windows

To download and install the binary distribution on a Windows system, complete the following steps:

  1. Download the ServiceMix distribution file for Windows from ServiceMix
  2. Extract the files from the zip file into a directory of your choice

To start ServiceMix, in a console window, change to the ServiceMix installation directory as follows:

 cd [servicemix_install_dir]\bin

Replace servicemix_install_dir with the directory in which ServiceMix was installed, e.g., c:\Program Files\servicemix-1.x. Then in the console window, type servicemix.

Installing and starting ServiceMix on Unix

To download and install the binary distribution on a Unix system:

  1. Download the ServiceMix distribution file for Unix. Change to the directory where ServiceMix was downloaded. Extract the files from the gzip file into a directory of your choice. For example:
     gunzip servicemix-x.x.x.tar.gz
    tar xvf servicemix-x.x.x.tar
    
  2. If the ServiceMix startup script is not executable, change its permissions. The ServiceMix script is located in the bin directory. To change the permissions, use the following examples, where [servicemix_install_dir] is the directory in which ServiceMix was installed:

     cd [servicemix_install_dir]/bin
    chmod 755 servicemix
    

To start ServiceMix, from a command shell, change to the installation directory and run the ServiceMix program: cd [servicemix_install_dir]/bin.

Replace servicemix_install_dir with the directory in which ServiceMix was installed. Then type servicemix.

Testing the installation

If ServiceMix is up and running correctly, the Window's console window or the Unix command shell displays something similar to the following line:

 [INFO] JBIContainer -- ServiceMix JBI Container 
<http://servicemix.org/> name: defaultJBI running version: null

Stopping ServiceMix

For both Windows and Unix installations, terminate ServiceMix by typing CTRL-C in the command shell or console in which it is running.

If ServiceMix was started in the background on Unix, the process can be killed, as follows:

 ps -ef|grep servicemix
kill [PID]

Replace [PID] with the actual process ID of the ServiceMix process.

Conclusion

Services using a service-oriented architecture (SOA) require an infrastructure that can connect any component or service, regardless of location, messaging protocol, and message format. An enterprise service bus (ESB) fulfills these requirements.

The JBI specification and API defines a normalized messaging service, component framework, and management model for building a standards-based and pluggable ESB. ServiceMix is a lightweight, open source ESB and SOA toolkit built on the semantics and APIs of the JBI specification and released under the Apache license. ServiceMix is easily embeddable and can run as a standalone ESB.

In this article, I discussed the mechanisms used by the ServiceMix ESB to facilitate cross-protocol messaging, message transformation, message security, service invocation, and other requirements of a service-oriented messaging infrastructure.

Jeff Hanson has more than 20 years of experience in the software industry, including working as senior engineer for the Windows OpenDoc project and as lead architect for the Route 66 framework at Novell. An author of numerous articles and books, he is currently the chief architect for eReinsure.com, building Web service frameworks and platforms for J2EE-based reinsurance systems.

Learn more about this topic

1 2 Page 2
Page 2 of 2