An ESB "Hello, world!" Application
Let's examine what it takes to get similar functionality from an application built on top of an ESB. Here's overview of the steps you take to build and run this sample ESB-based application:
- Download and install an ESB (in this case, ServiceMix)
- Build the individual message sender and message receiver components
- Write the "Hello, World!" ESB application configuration file
- Start the ESB
- Run the ESB-based "Hello, World!" application (which entails running the sender and receiver components)
Download and Install ServiceMix. The first step is to download and install an ESB, such as ServiceMix, which is an open-source ESB made available from LogicBlaze. As mentioned in the previous section, ServiceMix offers a great deal of flexibility in terms of its deployment and integration options and, as a result, will be used extensively throughout this book. At the time of this writing, ServiceMix is at version 2.0.2, and is part of the Apache Inubator project, which is the entry path into the Apache Software Foundation (ASF) for software projects wishing to become part of the Foundation's efforts. All code donations from external organizations and existing external projects wishing to join Apache enter through the Incubator.
Go ahead and download the latest ServiceMix binary and source. The software is available in multiple compressed formats, such as .ZIP for Windows and .GZ for Unix variants (such as Linux and Solaris), so be sure to download the proper file for your system. Additionally, you can choose to download ServiceMix with or without the source; the file with the text "src" in its name (such as servicemix-3.1-src.tar.gz) contains the binaries and full source code, along with the maven and ant scripts to build it. It's recommended that you download ServiceMix with full source code. You don't need to touch the source if you don't want to, but it's there if you want to explore it at some point.
Next, you can to uncompress the SeviceMix files to your computer's hard drive in a location of your choice. When the file is uncompressed, a subdirectory will be created with the name "servicemix" along with the version number (i.e. "servicemix-3.1"). Where you choose to uncompress the file, and hence create the ServiceMix subdirectory, is entirely up to you. However, on a Unix-based system, a good location is the /usr/local directory or your home directory. On Windows it's a good idea to simply uncompress the file at the root of your hard drive, which will result in a c:\servicemix-3.1 subdirectory, for example. Regardless of where you choose to place it, the ServiceMix subdirectory will contain all the ServiceMix source, binary, and configuration files needed to develop and run an ESB-based application.
Writing the Application Code. The sample application we're exploring here consists of a class that both sends, and waits to receive, a message that contains the text "Hello, world!" The ESB will be configured to route this message from the sender to the receiver, based simply on messaging topic names.
Listing One is the code to send and listen for the message for the JMS Client. No code needs to be written for the message routing; proper configuration is all that is required.
import javax.jms.*; import org.activemq.ActiveMQConnectionFactory; import org.activemq.message.ActiveMQTopic; public class JMSClient { public static void main(String[] args) throws JMSException { // ActiveMQ JMS Provider code ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616"); ActiveMQTopic pubTopic = new ActiveMQTopic("demo.esb.source"); ActiveMQTopic subTopic = new ActiveMQTopic("demo.esb.result"); System.out.println("Connecting to JMS server."); Connection connection = factory.createConnection(); Session session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE); // Create the message producer and consumer MessageProducer producer = session.createProducer(pubTopic); MessageConsumer consumer = session.createConsumer(subTopic); connection.start(); System.out.println("Sending request."); producer.send( session.createTextMessage( <message>Hello, world!</message>")); // Wait up to 10 seconds to receive the message TextMessage m = (TextMessage)consumer.receive(1000*10); if( m == null ) System.out.println("Response timed out."); else System.out.println("Response was: "+m.getText()); connection.close(); System.out.println("Done."); } }
Listing One is a straightforward JMS client. For simplicity, both the sender and receiver components have been placed in the same class. In reality, these components would most likely be separate entities; developed and deployed individually without any dependencies on one another. Although it's true that this code needs nothing more than a JMS provider, the point is that this application will run in an ESB without the need for any ESB-specific code. All that is needed now is some configuration on the ESB side to make this application work, and to route the "Hello, world!" message properly from the sender to the receiver.
The ServiceMix ESB needs a configuration file, named servicemix.xml, to operate properly and in the manner you expect. Listing Two contains a portion of the servicemix.xml file for the "Hello, world!" sample application. The listing sets up a JMS consumer within the ESB to subscribe to a JMS destination.
... <!-- Subscribe to a JMS destination --> <sm:activationSpec componentName="inputReceiver" service="my:inputReceiver" destinationService="my:outputSender"> <sm:component> <bean xmlns="http://xbean.org/schemas/spring/1.0" class="org.servicemix.components.jms.JmsInUsingJCABinding"> <property name="jcaContainer" ref="jencks"/> <property name="activationSpec"> <bean class="org.activemq.ra.ActiveMQActivationSpec"> <property name="destination" value="demo.esb.source"/> <property name="destinationType" value="javax.jms.Topic"/> </bean> </property> </bean> </sm:component> </sm:activationSpec> ...
The first XML tag in the XML contains an attribute, componentName, which provides a name for the component ("inputReceiver" in this case). The other <property> tags specify features of the component, such as that it uses ActiveMQ for activation and message deliver, and that a JMS topic is to be used as the destination. Therefore, in this portion of the file, the ESB is instructed to internally create a consumer to subscribe to the topic, demo.esb.source, which is the topic to which the producer from Listing One sends a message.
Receiving the message from the client's producer component is only half of the story. To complete the picture, and the "Hello, world!" message's journey, a message producer must be created within the ESB to route the message to the client's consumer component.
Listing Three contains another portion of the servicemix.xml configuration file; this time with the piece that creates the internal JMS message producer. This producer is configured to send the messages received by the internal message consumer, from Listing Two, to the topic, demo.esb.result, which is the topic that the client's consumer is listening to.
<!-- Publish the result to a JMS destination --> <sm:activationSpec componentName="outputSender" service="my:outputSender"> <sm:component> <bean xmlns="http://xbean.org/schemas/spring/1.0" class="org.servicemix.components.jms.JmsSenderComponent"> <property name="template"> <bean class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory"> <ref local="jmsFactory"/> </property> <property name="defaultDestinationName" value="demo.esb.result"/> <property name="pubSubDomain" value="true"/> </bean> </property> </bean> </sm:component> </sm:activationSpec>
You can see that this portion of the XML configuration file is similar to Listing Two, with some important differences. The big difference is that the component is specified to be a JMS sender, as shown in the <bean> tag's class attribute. The destination, in the case of this component, is also a topic. The ESB will take on the responsibility of delivering all messages reliable via its built-in JMS provider.