10.2. Apache Camel JMS-to-JMS Bridge

10.2.1. Configuring the Broker

Overview

You need to modify the broker configuration in order to add a VM transport connector.
Note
This is the only modification you should make to the broker configuration file. The Apache Camel JMS-to-JMS bridge must not be embedded inside the broker configuration file. The broker configuration file is not a regular Spring XML file: it is used by a specialized sevice factory, which controls the broker life cycle.

Broker configuration file

In a standalone container, the broker is configured by the following file:
InstallDir/etc/activemq.xml

Adding a VM transport connector

To ensure efficient communication between the Apache Camel JMS-to-JMS bridge and the broker, create a Virtual Machine (VM) transport connector on the broker. Th VM protocol provide a high performace connection between processes that are running inside the same Java Virtual Machine. Example 10.1, “Embedded Apache Camel JMS-to-JMS Bridge” shows how to add a VM connector to the broker configuration in the etc/activemq.xml file.

Example 10.1. Embedded Apache Camel JMS-to-JMS Bridge

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ... >
  ...
  <broker xmlns="http://activemq.apache.org/schema/core"
          brokerName="${broker-name}"
          dataDirectory="${data}"
          start="false">
    ...
    <transportConnectors>
      <transportConnector name="openwire" uri="tcp://0.0.0.0:0?maximumConnections=1000"/>
      <!-- Create a VM endpoint to enable embedded connections -->
      <transportConnector uri="vm://local" />
    </transportConnectors>

  </broker>
  ...
</beans>

10.2.2. Configuring ActiveMQ JMS Connections

The Camel ActiveMQ component

The Camel ActiveMQ component (hosted in the Apache ActiveMQ project) is a Camel component that is used to integrate the Apache ActiveMQ Java client with Camel. Using the Camel ActiveMQ component, it is possible to define JMS consumer endpoints (at the start of a Camel route) and JMS producer endpoints (at the end of a Camel route).

Apache Camel bridge configuration file

The simplest way to configure the Apache Camel JMS-to-JMS file is to create a Spring XML file and copy it into the hot deploy directory. For the current example, we assume that the bridge configuration is stored in the following file:
InstallDir/deploy/jms-bridge.xml
Note
Subsequently, if you need to undeploy the Spring XML file, you can do so by deleting the jms-bridge.xml file from the deploy/ directory while the Karaf container is running.

Spring XML example

The following code example shows how to define and configure a Camel ActiveMQ endpoint by adding Spring XML code to the bridge configuration file, InstallDir/deploy/jms-bridge.xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ... >
  ...
  <!--
    -- Configure the ActiveMQ broker connection
    -->
  <bean id="amqConnectionFactory"
        class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="vm://local?create=false"/>
  </bean>

  <bean id="jmsConfig" 
        class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="amqConnectionFactory"/>
    <property name="concurrentConsumers" value="10"/>
  </bean>

  <bean id="activemq" 
        class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="configuration" ref="jmsConfig"/>
  </bean>
  ...
</beans>
Note the following points about this example:
  • The bean with ID, activemq, and of type, ActiveMQComponent, defines the Camel ActiveMQ component instance. This bean overrides the default ActiveMQ component instance and implicitly associates the bean ID value, activemq, with the URI scheme of the same name. The activemq URI scheme can then be used to define endpoints of this component in a Camel route.
  • The bean with ID, jmsConfig, is used to configure the ActiveMQ component (and supports many additional options).
  • The bean with ID, amqConnectionFactory, is a JMS connection factory that is used to create connections to the ActiveMQ broker. Note the following attribute settings:
    • The brokerURL attribute specifies the transport protocol for connecting to the broker. In this case, the protocol is vm://local, which uses the Java Virtual Machine to route messages directly to and from the embedded broker.

Defining an endpoint with the activemq scheme

The bean ID of the ActiveMQ component (in this example, activemq) is implicitly adopted as the URI scheme for defining ActiveMQ endpoints in Camel routes. For example, to define an endpoint that connects to the QueueA queue in the ActiveMQ broker, use the following URI:
activemq:queue:QueueA
To define an endpoint that connects to the TopicA topic in the ActiveMQ broker, use the following URI:
activemq:topic:TopicA

Other types of ActiveMQ connection factory

ActiveMQ provides a variety of different types of JMS connection factory, as follows:
ActiveMQConnectionFactory
For ordinary JMS connections (includes support for JMS authentication).
ActiveMQSslConnectionFactory
For configuring JMS connections over SSL/TLS (encrypted transport).
ActiveMQXAConnectionFactory
For integrating the ActiveMQ client with an XA transaction manager.

References

For more details about the Camel ActiveMQ component, see the following references:
  • The ActiveMQ component chapter from the EIP Component Reference.
  • The community documentation for the ActiveMQ Component.

10.2.3. Configuring Third-Party JMS Connections

The Camel JMS component

The Camel JMS component is a general purpose JMS integration point that can be used to integrate Apache Camel with any JMS client library. Using the Camel JMS component, it is possible to define JMS consumer endpoints (at the start of a Camel route) and JMS producer endpoints (at the end of a Camel route).

Alternative approaches

You can connect to a third-party JMS broker using either of the following approaches:

Reference a connection factory bean

You can configure connections to a third-party JMS provider by instantiating a javax.jms.ConnectionFactory instance directly as a Spring bean. You can then inject this third-party connection factory bean into the configuration of the Camel JMS component.
For example, you can instantiate and reference a WebSphere MQ queue connection factory by adding the following XML code to the bridge configuration, deploy/jms-bridge.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ... >
  ...
  <!-- Configure IBM WebSphere MQ connection factory -->
  <bean id="websphereConnectionFactory"
        class="com.ibm.mq.jms.MQConnectionFactory">
    <property name="transportType" value="1"/>
    <property name="hostName" value="localhost"/>
    <property name="port" value="1414"/>
    <property name="queueManager" value="QM_TEST"/>
  </bean>

  <bean id="websphereConfig" 
        class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="websphereConnectionFactory"/>
    <property name="concurrentConsumers" value="10"/>
  </bean>

  <bean id="websphere" 
        class="org.apache.camel.component.jms.JmsComponent">
    <property name="configuration" ref="websphereConfig"/>
  </bean>
  ...
</beans>

Look up a connection factory in JNDI

You can use JNDI to configure connections to a third-party JMS provider by configuring the destinationResolver attribute of Camel's JmsComponent class to reference a Spring JndiDestinationResolver instance.
For example, to look up a WebSphere MQ connection factory in an LDAP based JNDI server, you could add the following XML code to the bridge configuration file, deploy/jms-bridge.xml, as follows:
<beans ... >
  ...
  <!-- Configure a Spring JNDI template instance -->
  <bean id="jmsJndiTemplate"
        class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
      <props>
        <prop key="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</prop>
        <prop key="java.naming.provider.url">ldap://server.company.com/o=company_us,c=us</prop>
      </props>
    </property>
  </bean>

  <bean id="jmsConnectionFactory"
        class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate" ref="jmsJndiTemplate"/>
    <property name="jndiName" value="jms/websphere-test"/>
  </bean>

  <bean id="jndiDestinationResolver"
        class="org.springframework.jms.support.destination.JndiDestinationResolver">
    <property name="jndiTemplate" ref="jmsJndiTemplate"/>
  </bean>

  <bean id="websphereConfig"
        class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <property name="destinationResolver" ref="jndiDestinationResolver"/>
    <property name="concurrentConsumers" value="10"/>
  </bean>

  <bean id="websphere" 
        class="org.apache.camel.component.jms.JmsComponent">
    <property name="configuration" ref="websphereConfig"/>
  </bean>
  ...
</beans>

References

For more details about the Camel JMS component, see the following references:
  • The JMS component chapter from the EIP Component Reference.
  • The community documentation for the JMS Component.

10.2.4. Defining Apache Camel Routes

Overview

Apache Camel is a sophisticated and flexible routing engine. At the simplest level, you can use it move JMS messages back and forth between an ActiveMQ broker and a third-party JMS provider. But Camel can do much more. You can insert processors into a route to process the message contents and Camel also has built in processors that implement a wide variety of Enterprise Integration Patterns.
The description in this section—which shows you how to define simple pass-through routes—only scratches the surface of Camel's capabilities. It is recommended that you take a look at some of the references at the end of this section to get a better idea of Camel's capabilities.

JMS endpoint syntax

To create a JMS endpoint in an Apache Camel route, specify an endpoint URI according to the following queue syntax:
JmsUriScheme:queue:QueueName[?Options]
Or according to the following topic syntax:
JmsUriScheme:topic:TopicName[?Options]
Where the URI scheme, JmsUriScheme, is equal to the bean ID of the corresponding JMS component (or ActiveMQ component) defined in Spring XML—for example, activemq or websphere.

Route syntax

In the XML language, Camel routes are defined inside a camelContext element. Each route definition appears inside a route element, starting with a from element (which defines a consumer endpoint for receiving messages) and ending with a to element (which defines a producer endpoint for sending messages).
For example, to perform simple, straight-through routing, consuming messages from the TEST.FOO queue on the ActiveMQ broker and passing them straight on to the TEST.FOO queue on the WebSphere messaging system, you can use the following route definition:
<camelContext xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="activemq:queue:TEST.FOO"/>
    <to uri="websphere:queue:TEST.FOO"/>
  </route>
</camelContext>

Sample routes

The following sample Camel routes give examples of how to route queues and topics into and out of the ActiveMQ broker. To define these routes, you would add them to the bridge configuration file, InstallDir/deploy/jms-bridge.xml.
<beans ... >
  ...
  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <!-- Route outgoing QueueA queue -->
    <route>
      <from uri="activemq:queue:QueueA?mapJmsMessage=false"/>
      <to uri="websphere:queue:QueueA"/>
    </route>

    <!-- Route outgoing TopicA topic -->
    <route>
      <from uri="activemq:topic:TopicA?mapJmsMessage=false"/>
      <to uri="websphere:topic:TopicA"/>
    </route>

    <!-- Route incoming QueueX queue -->
    <route>
      <from uri="websphere:queue:QueueX?mapJmsMessage=false"/>
      <to uri="activemq:queue:QueueX"/>
    </route>

    <!-- Route incoming TopicX topic -->
    <route>
      <from uri="websphere:topic:TopicX?mapJmsMessage=false"/>
      <to uri="activemq:topic:TopicX"/>
    </route>

  </camelContext>
</beans>

mapJmsMessage option

In the preceding example, the consumer endpoints are configured with the mapJmsMessage set to false. This prevents the JMS message from being parsed into the standard Java data format, thus ensuring that the message is passed straight through without processing, which gives optimum performance for a pass-through route.
On the other hand, if you want to perform any processing on the message content or the message headers, you should remove this option (or set it to true).

Camel schema location

If you want to take advantage of the content completion feature of your XML editor, you can configure your editor to fetch the Camel schema from the following location:
http://camel.apache.org/schema/spring/camel-spring.xsd
The preceding location always holds the latest version of the Camel schema. If you want to specify a particular version of the schema, you can use the version-specific location:
http://camel.apache.org/schema/spring/camel-spring-Version.xsd

References

Apache Camel is a sophisticated routing and integration tool. To get a better idea of the capabilities of this tool, please consult the following guides from the JBoss Fuse library:
  • Implementing Enterprise Integration Patterns
  • Routing Expression and Predicate Languages
  • EIP Component Reference