Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Creating a Protocol Bridge

ServiceMix can be used as a protocol bridge. The following tutorial will explain how to create a JBI Service Assembly (aka a JBI application) to bridge two different protocolsto create applications that serve as a bridge between two different protocols. Messages flow in via one protocol and out the other protocol. In this example, we will bridge the HTTP /SOAP protocol with the JMS protocol using an InOnly message exchange pattern (MEP). We will also put between place an XSLT transformation service between the two protocols an XSLT transformation.
We will leverage ServiceMix archetypes and maven plugin (see Maven JBI plugin).to further demonstrate that a service is not tied to a given protocol.

The following tutorial will explain how to create a JBI Service Assembly (aka a JBI application) to serve as a bridge between two different protocols. This tutorial will leverage some Maven archetypes for ServiceMix and also the Maven JBI plugin.

This tutorial has This tutorial has been written for ServiceMix 3.12 or greater. For ServiceMix 3.0, see this page.

Identifying the

...

JBI Service Units

Our JBI SA ( Service Assembly (SA) will be composed of the following SUs ( JBI Service Units (SUs)):

  • an An HTTP+SOAP consumer
  • a A EIP pipeline to call the XSLT transformer and the JMS provider
  • an An XSLT transformer
  • a A JMS provider

Directory layout

We aim to have the following project structure:

Code Block
bridge\/
  pom.xml
  bridge-http-su\/
    ...
  bridge-eip-su\/
    ...
  bridge-xslt-su\/
    ...
  bridge-jms-su\/
    ...
  bridge-sa\/
    ...

Creating the Service Units

In the bridge directory, run the following commands (remove tailing backslashes and make each command on one line) to create the JBI service units (SUs)First, create a directory named bridge and move into that directory:

Code Block
mvn$ archetype:createmkdir \bridge
$        -DarchetypeGroupId=org.apache.servicemix.tooling \
        -DarchetypeArtifactId=servicemix-http-consumer-service-unit \
        -DarchetypeVersion=3.1-incubating \
        -DgroupId=orgcd bridge

Create a file in the bridge directory named pom.xml and copy/paste the following content:

Code Block
langxml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>org.apache.servicemix.samples.bridge \bridge</groupId>
  <artifactId>bridge</artifactId>
  <packaging>pom</packaging>
    -DartifactId=bridge-http-su \<version>1.0-SNAPSHOT</version>
  <name>ServiceMix Bridge Demo</name>

</project>

This is known as the root pom.xml because it is for the main bridge project. We'll come back to this in a bit.

In the bridge directory, run the following commands (remove the trailing backslashes and make each command fit on one line) to create the JBI service units (SUs):

Code Block

$ mvn archetype:create     -DremoteRepositories=http://people.apache.org/repo/m2-incubating-repository

mvn archetype:create \
        -DarchetypeGroupId=org.apache.servicemix.tooling \
        -DarchetypeGroupId=org.apache.servicemix.tooling \
        -DarchetypeArtifactId=servicemix-jmshttp-providerconsumer-service-unit \
        -DarchetypeVersion=3.2.1-incubating \
        -DgroupId=org.apache.servicemix.samples.bridge \
        -DartifactId=bridge-jmshttp-su 

mvn archetype:create \
        -DremoteRepositories=http://people.apache.org/repo/m2-incubating-repository

mvn archetype:create \DarchetypeGroupId=org.apache.servicemix.tooling \
        -DarchetypeGroupIdDarchetypeArtifactId=org.apache.servicemix.tooling \
        -DarchetypeArtifactId=servicemix-eip-jms-provider-service-unit \
        -DarchetypeVersion=3.2.1-incubating \
        -DgroupId=org.apache.servicemix.samples.bridge \
        -DartifactId=bridge-eipjms-su 

mvn archetype:create \
        -DremoteRepositories=http://people.apache.org/repo/m2-incubating-repository

mvn archetype:create \
        -DarchetypeGroupId=orgDarchetypeGroupId=org.apache.servicemix.tooling \
        -DarchetypeArtifactId=servicemix-saxon-xslteip-service-unit \
        -DarchetypeVersion=3.2.1-incubating \
        -DgroupId=org.apache.servicemix.samples.bridge \
        -DartifactId=bridge-xslteip-su 

mvn archetype:create \
        -DremoteRepositories=http://peopleDarchetypeGroupId=org.apache.org/repo/m2-incubating-repository

mvn archetype:create.servicemix.tooling \
        -DarchetypeArtifactId=servicemix-saxon-xslt-service-unit \
        -DarchetypeGroupIdDarchetypeVersion=org3.apache2.servicemix.tooling1 \
        -DarchetypeArtifactIdDgroupId=org.apache.servicemix-service-assembly \
        -DarchetypeVersion=3.1-incubating \
        -DgroupId=org.apache.servicemix.samples.bridge \
        -DartifactId=bridge-sa \
        -DremoteRepositories=http://people.apache.org/repo/m2-incubating-repository

Main pom

Now that we have created the SUs and SA structure, let's write the main pom.xml (in the bridge directory):

.samples.bridge \
        -DartifactId=bridge-xslt-su 

mvn archetype:create \
        -DarchetypeGroupId=org.apache.servicemix.tooling \
        -DarchetypeArtifactId=servicemix-service-assembly \
        -DarchetypeVersion=3.2.1 \
        -DgroupId=org.apache.servicemix.samples.bridge \
        -DartifactId=bridge-sa 

Each of the commands above will create a directory containing a Maven project skeleton that is ready to be configured. The rest of the tutorial will focus on this.

Back to the Root pom.xml

Now that we have created the SUs and SA structure, let's take a look at the root pom.xml. Below is what you should see now:

Code Block
langxml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
Code Block
langxml

<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.apache.servicemix.samples.samples<bridge</groupId>
  <artifactId>bridge</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>ServiceMix Bridge <packaging>pom<Demo</packaging>name>

  <modules>
    <module>bridge-http-su</module>
    <module>bridge-eipjms-su</module>
    <module>bridge-xslteip-su</module>
    <module>bridge-jmsxslt-su</module>
    <module>bridge-sa</module>
  </modules>

</project>

The content of <version> describes not the version of ServiceMix but the SA we create, thus you may change it to your desired version (e.g. 3.0-final). Then you have to change it below as wellThis is what allows all the projects to be built using a single command from the bridge directory. Maven will descend into each subproject directory, figure out the order in which to build each subproject and build them all.

Configure the Service Assembly

We want the JBI Service Assembly to include the 4 four SUs that we just created.
So let's edit the bridge-sa pom we created .xml and add the <dependencies> which is a child of <project>:

...

Now, we should be able to launch maven and have build from the bridge directory and Maven will generate the SA generated in the bridge-sa/target/ directory. You can check that by running So let's run the following command from the bridge / directory:

Code Block
mvn install

Of course, it won't work if you deploy it and we now need to fill the holesBut this is just to make sure that everything builds correctly. Now we need to go through each subproject and configure each SU.

HTTP SU

We need to define a simple HTTP consumer endpoint in the http HTTP SU. As we do not use the request/response pattern, we will use an InOnly mep.MEP. Now you need to edit the src/main/resources/xbean.xml for the HTTP SU to match the following:

Code Block
langxml
<?xml version="1.0"?>
<beans xmlns:http="http://servicemix.apache.org/http/1.0"
       xmlns:b="http://servicemix.apache.org/samples/bridge">

  <http:endpoint service="b:http"
                 endpoint="endpoint"
                 targetService="b:pipeline"
                 role="consumer"
                 locationURI="http://localhost:8192/bridge/"
                 defaultMep="http://www.w3.org/2004/08/wsdl/in-only" />

</beans>

...

The EIP SU contains the definition of the pipeline pattern, which can be used as a bridge between two InOnly MEPs and an InOut MEP. The XSLT transformer primary MEP is an InOut, as it will receive an incoming message, transform it, and send the answer back to the consumer. But in our case, the HTTP component and JMS component should send and receive an InOnly MEP, hence the need for the Pipeline.hence the need for the pipeline. Edit the src/main/resources/xbean.xml file for the EIP SU to match the following:

Code Block
langxml
<?xml version="1.0"?>
<beans xmlns:eip="http://servicemix.apache.org/eip/1.0"
       xmlns:b="http://servicemix.apache.org/samples/bridge">

  <eip:pipeline service="b:pipeline" endpoint="endpoint">
    <eip:transformer>
      <eip:exchange-target service="b:xslt" />
    </eip:transformer>
    <eip:target>
      <eip:exchange-target service="b:jms" />
    </eip:target>
  </eip:pipeline>

</beans>

...

The XSLT transformation will be deployed on to the servicemix-saxon SE JBI service engine using the following xbean.xml configuration file.:

Code Block
langxml
<?xml version="1.0"?>
<beans xmlns:saxon="http://servicemix.apache.org/saxon/1.0"
       xmlns:b="http://servicemix.apache.org/samples/bridge">

  <saxon:xslt service="b:xslt" endpoint="endpoint"
              result="string"
              resource="classpath:bridge.xslt" />

</beans>

Note the classpath:bridge.xsdl uri URI used to point to the XSLTXSL stylesheet. The classpath is automatically defined by the component and includes the root directory of the SU (see Classloaders).

We need to create the bridge.xslt stylesheet and put in it in the src/main/resources directory of this SU, along the xbean.xml configuration file.
Let's use an the following identity stylesheet:

Code Block
langxml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

</xsl:stylesheet>

Nothing special in the stylesheet above. It just copies all nodes and attributes.

JMS SU

For the JMS provider, we will reuse the embedded ActiveMQ broker which is started with ServiceMix, and output send the request in the bridge.output JMS queue.:

Code Block
langxml
<?xml version="1.0"?>
<beans xmlns:jms="http://servicemix.apache.org/jms/1.0"
       xmlns:b="http://servicemix.apache.org/samples/bridge">

  <jms:endpoint service="b:jms"
                endpoint="endpoint"
                role="provider"
                destinationStyle="queue"
                jmsProviderDestinationName="bridge.output"
                connectionFactory="#connectionFactory" />

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

</beans>

...

Then you can send an HTML POST request to http://localhost:8192/bridge/ and use a jmx console to check that the bridge.output queue contains a jms messagebridge/ and use a JMX console to check that the bridge.output queue contains a JMS message.

Summary

This tutorial has demonstrated how to send a message to a URL via the HTTP protocol and route that message through a XSLT transformation service and on to a JMS queue via the JMS protocol. Although this is a simple demonstration of what ServiceMix can do, it is a good start to illustrate just one use case.

What's

...

Next?

Of course, this example is not very useful as is, especially with an identity XSLT sheet. However, adding an xpath XPath router as the target of the pipeline, could be useful to normalize different requests to the same format, because the XSD changed between versions of the service, or because different clients use different XSDs which can be services by the same service.