Enterprise Integration Zone is brought to you in partnership with:

OpenSource has posted 2 posts at DZone. View Full User Profile

Pattern Based Development with ServiceMix

06.10.2008
| 82874 views |
  • submit to reddit

Build a ServiceMix 3.2.1 message flow

In the first article about Mule, we introduced a hello world example, showing the basics of the Mule configuration. So let’s implement the same example with ServiceMix. First we need to select the BCs and SEs we will use in the implementation of the hello world example. First, we need JMS connectivity to receive and send messages in the ServiceMix container, so we need a JMS BC.

Then we need to implement a simple Java bean, which returns the input name parameter with an injected prefix. We can implement this functionality with at least two SEs: the Bean SE and the JSR181 SE. In this example we will use the JSR181 SE, because this SE provides a nice abstraction layer from JBI and the ServiceMix container, while the Bean SE provides functionality for more advanced use cases. In figure 3 an overview is provided of the SUs that we need to create for the hello world SA.

Figure 3 An overview of the service units that we need to implement for the hello world example.

We will implement a JMS consumer with a JMS BC configuration and a HelloComponent configuration and implementation with the JSR181 SE. The configuration within ServiceMix is implemented with the Apache XBean framework, which is a sub-project of the Apache Geronimo project. The XBean framework makes it easy to define your own configuration language with out-of-the-box support for, for example, Spring. The SU configuration in ServiceMix is implemented with an xbean.xml file, which uses a set of elements and attributes specific to the BC or SE. In listing 1 the configuration for the JMS BC is shown, which uses the XBean configuration of the JMS BC.

Listing 1 JMS configuration for the simple example in ServiceMix

<beans xmlns:jms="http://servicemix.apache.org/jms/1.0"
xmlns:esb="http://esbinaction.com/simple">

<jms:consumer service="esb:simpleReceiver"
endpoint="jmsEndpoint"
targetService="esb:helloComponent"
destinationName="in-queue"
replyDestinationName="out-queue"
connectionFactory="#connectionFactory"
marshaler="#replyInOutMarshaler"/>

<bean id="replyInOutMarshaler"
class="org.apache.servicemix.jms.endpoints.DefaultConsumerMarshaler">
<property name="mep" value="http://www.w3.org/2004/08/wsdl/in-out" />
</bean>

<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
</beans>

The JMS BC configuration uses a beans root element, which refers to the Spring configuration language. As you can see the ServiceMix JMS BC namespace is declared at root level. The JMS consumer declaration, which uses the JMS BC namespace, configures most of the JMS functionality we need. The destinationName and replyDestinationName attributes tell the JMS BC to respectively listen for messages on the in-queue and sent response messages to the out-queue.

It may seem a bit strange at first sight that we also configure a response destination in a JMS consumer. This choice is related to the use of message exchange patterns (MEPs) within JBI and ServiceMix. For every message consumed by the ServiceMix container a message exchange will be created with a specific MEP. The concept of MEPs is introduced in the WSDL specification and the supported MEPs in JBI are in-out, in-only, robust-in-only and optional-in-only. The most common MEPs are of course in-out and in-only and these MEPs are also related to our choice for the JMS BC configuration.

By default the JMS consumer uses an in-only MEP, so this means that a JMS message will be consumed from a queue and sent on in the ServiceMix container. But the JSR181 hello Java bean returns a response, and for an in-only MEP there can be no response message. So we need some way to transform the in-only MEP into an in-out MEP or use an in-out MEP in the JMS consumer. An overview of this decision is shown in figure 4.

Figure 4 An overview of the choice in MEPs and use of BCs and SEs for a JMS implementation.

Obviously, in listing 1 we have chosen for the second alternative shown in figure 4. We have configured the JMS consumer to use an in-out MEP with the DefaultConsumerMarshaler and the mep property. This means that the consumed JMS message is sent on to the HelloComponent and the JMS consumer waits for a response from this Java bean. The returned message is then sent to the reply destination, which in this in example is the out-queue.

An alternative implementation would be to use the default in-only MEP in the JMS consumer and transform the message exchange to an in-out MEP with the EIP SE pipeline. The pipeline can be used to transform an in-only MEP to an in-out MEP. The response of the HelloComponent is sent to a JMS provider also configured in the EIP pipeline configuration. An example configuration of the pipeline is shown in listing 2.

Listing 2 Example of an EIP pipeline configuration

<beans xmlns:eip="http://servicemix.apache.org/eip/1.0"
xmlns:esb="http://esbinaction.com/simple">

<eip:pipeline service="esb:examplePipeline"
endpoint="routingEndpoint">
<eip:transformer>
<eip:exchange-target service="esb:helloComponent" />
</eip:transformer>
<eip:target>
<eip:exchange-target service="esb:simpleSender" />
</eip:target>
</eip:pipeline>
</beans>

Listing 2 shows a definition of a pipeline element with transformer and target child elements. The transformer element defines the in-out exchange target, in this example the HelloComponent and the target element defines the target for the response message of the in-out exchange, which will be sent as an in-only MEP. So to implement integration solutions in a JBI container such as ServiceMix, a good understanding of the MEPs is needed. But with the overview described here you will be ready to start using ServiceMix for more complex integration cases.

Notice that in listings 1 and 2 we defined service, endpoint and targetService attributes. These attributes are very important in the ServiceMix container, because they define a unique identification for a component configuration within the ServiceMix container. So the service and endpoint attributes uniquely identifies the JMS consumer and EIP pipeline components within the ServiceMix container. And to invoke a service provider within the ServiceMix container, we can define a targetService and an optional targetEndpoint value that corresponds to the service and endpoint definition of that service provider. For example, in listing 1 we defined a targetService attribute with a value of esb:helloComponent, which should correspond to the JSR181 SE hello Java bean service configuration. Note that a service definition is always namespace qualified within ServiceMix.

Now let’s look at the configuration of the JSR181 SE in listing 3 and see if the service definition matches the targetService configuration of listing 1.

Listing 3 XBean configuration of the JSR181 hello Java bean

<beans xmlns:jsr181="http://servicemix.apache.org/jsr181/1.0"
xmlns:esb="http://esbinaction.com/simple">

<jsr181:endpoint annotations="none" service="esb:helloComponent" endpoint="endpoint"
serviceInterface="esb.example.HelloIF" id="hello">
<jsr181:pojo>
<bean id="helloBean" class="esb.example.HelloBean">
<property name="prefix" value="Hello "/>
</bean>
</jsr181:pojo>
</jsr181:endpoint>
</beans>

Notice that the JSR181 SE configuration uses a different namespace as the JMS BC and EIP SE examples of listings 1 and 2. The JSR181 endpoint definition surrounding the HelloBean configuration is actually just a wrapper to expose the HelloBean within the ServiceMix container with the service and endpoint definition. The JSR181 SE uses the XFire framework to provide the functionality to serialize and deserialize XML messages to and from the Java beans. Because within the ServiceMix container every message is XML, we need some way to serialize this Java and back again. That’s exactly what the JSR181 SE provides without additional configurations.

To be complete, listing 4 shows the implementation of the HelloIF interface and the HelloBean Java class.

Listing 4 HelloBean and HelloIF which is used in the JSR181 SE configuration


public interface HelloIF {
public String hello(String name);
}

public class HelloBean {

private String prefix;

public String hello(String name) {
return prefix + name;
}

public void setPrefix(String prefix) {
this.prefix = prefix;
}
}

Now we have created the service unit configurations for the JMS BC and the JSR181 SE, the last part remaining is the SA configuration. The JBI container needs a deployment descriptor (jbi.xml) that describes the service units included in the SA. Listing 5 shows the jbi.xml configuration for the hello world SA.

Listing 5 The JBI deployment descriptor, jbi.xml, for the hello world example

<jbi xmlns="http://java.sun.com/xml/ns/jbi" version="1.0">
<service-assembly>
<identification>
<name>simple-sa</name>
</identification>
<service-unit>
<identification>
<name>simple-jms-su</name>
</identification>
<target>
<artifacts-zip>simple-jms-su.zip</artifacts-zip>
<component-name>servicemix-jms</component-name>
</target>
</service-unit>
<service-unit>
<identification>
<name>simple-jsr181-su</name>
</identification>
<target>
<artifacts-zip>simple-jsr181-su.zip</artifacts-zip>
<component-name>servicemix-jsr181</component-name>
</target>
</service-unit>
</service-assembly>
</jbi>

We have now defined all the parts of the hello world example, so can now create the SU JAR files and the SA JAR file. In the SimpleSMDZone project included in the source code of this article, An Ant build file is included which creates these JAR files. And the ServiceMix project provides Ant targets to deploy the SA to the ServiceMix container. To get the example started, you can run the start target of the build.xml Ant build file to start the ServiceMix container. Then run the deploy-simple target to deploy the hello world SA.

This example can easily be tested with a JUnit class that sends a JMS message to the in-queue queue and listens for a response message on the out-queue. A JUnit class is also provided in the SimpleSMDZone project. Now let’s look at a more complex example, the insurance broker case study which we also implemented in the first article about Mule.

Published at DZone with permission of its author, OpenSource ESB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)