Tutorial on Spring Remoting with JMS
This tutorial was kindly donated to Apache Camel by Martin Gilday.
This tutorial aims to guide the reader through the stages of creating a project which uses Camel to facilitate the routing of messages from a JMS queue to a Spring service. The route works in a synchronous fashion returning a response to the client.
This tutorial uses Maven to setup the Camel project and for dependencies for artifacts.
This sample is distributed with the Camel distribution as
This tutorial is a simple example that demonstrates more the fact how well Camel is seamless integrated with Spring to leverage the best of both worlds. This sample is client server solution using JMS messaging as the transport. The sample has two flavors of servers and also for clients demonstrating different techniques for easy communication.
The Server is a JMS message broker that routes incoming messages to a business service that does computations on the received message and returns a response.
We use the following Camel components:
Create the Camel Project
For the purposes of the tutorial a single Maven project will be used for both the client and server. Ideally you would break your application down into the appropriate components.
Update the POM with Dependencies
First we need to have dependencies for the core Camel jars, its spring, jms components and finally ActiveMQ as the message broker.As we use spring xml configuration for the ActiveMQ JMS broker we need this dependency:
Writing the Server
Create the Spring Service
For this example the Spring service (= our business service) on the server will be a simple multiplier which trebles in the received value.And the implementation of this service is: Notice that this class has been annotated with the @Service spring annotation. This ensures that this class is registered as a bean in the registry with the given name multiplier.
Define the Camel RoutesThis defines a Camel route from the JMS queue named numbers to the Spring bean named multiplier. Camel will create a consumer to the JMS queue which forwards all received messages onto the the Spring bean, using the method named multiply.
The Spring config file is placed under
Notice that we also have enabled the JMXAgent so we will be able to introspect the Camel Server with a JMX Console. The ActiveMQ JMS broker is also configured in this xml file. We set it up to listen on TCP port 61610. As this examples uses JMS then Camel needs a JMS component that is connected with the ActiveMQ broker. This is configured as shown below: Notice: The JMS component is configured in standard Spring beans, but the gem is that the bean id can be referenced from Camel routes - meaning we can do routing using the JMS Component by just using jms: prefix in the route URI. What happens is that Camel will find in the Spring Registry for a bean with the id="jms". Since the bean id can have arbitrary name you could have named it id="jmsbroker" and then referenced to it in the routing as
We use the vm protocol to connect to the ActiveMQ server as its embedded in this application.
Run the Server
The Server is started using the
In this sample as there are two servers (with and without AOP) we have prepared some profiles in maven to start the Server of your choice.
Writing The Clients
This sample has three clients demonstrating different Camel techniques for communication
Client Using The ProducerTemplate
We will initially create a client by directly using
And the CamelClient source code:The
Before running the client be sure that both the ActiveMQ broker and the
Client Using Spring Remoting
Spring Remoting "eases the development of remote-enabled services". It does this by allowing you to invoke remote services through your regular Java interface, masking that a remote service is being called.The snippet above only illustrates the different and how Camel easily can setup and use Spring Remoting in one line configurations.
The proxy will create a proxy service bean for you to use to make the remote invocations. The serviceInterface property details which Java interface is to be implemented by the proxy. serviceUrl defines where messages sent to this proxy bean will be directed. Here we define the JMS endpoint with the "numbers" queue we used when working with Camel template directly. The value of the id property is the name that will be the given to the bean when it is exposed through the Spring
And the Java client source code:Again, the client is similar to the original client, but with some important differences.
Client Using Message Endpoint EIP Pattern
This client uses the Message Endpoint EIP pattern to hide the complexity to communicate to the Server. The Client uses the same simple API to get hold of the endpoint, create an exchange that holds the message, set the payload and create a producer that does the send and receive. All done using the same neutral Camel API for all the components in Camel. So if the communication was socket TCP based you just get hold of a different endpoint and all the java code stays the same. That is really powerful.
Okay enough talk, show me the code!Switching to a different component is just a matter of using the correct endpoint. So if we had defined a TCP endpoint as:
Run the Clients
The Clients is started using their main class respectively.
In this sample we start the clients using maven:
Also see the Maven
Using the Camel Maven Plugin
The Camel Maven Plugin allows you to run your Camel routes directly from Maven. This negates the need to create a host application, as we did with Camel server, simply to start up the container. This can be very useful during development to get Camel routes running quickly.
All that is required is a new plugin definition in your Maven POM. As we have already placed our Camel config in the default location (camel-server.xml has been placed in META-INF/spring/) we do not need to tell the plugin where the route definitions are located. Simply run
Using Camel JMX
Camel has extensive support for JMX and allows us to inspect the Camel Server at runtime. As we have enabled the JMXAgent in our tutorial we can fire up the jconsole and connect to the following service URI:
In the screenshot below we can see the route and its performance metrics: