JMS messaging with Camel (and in general) is asynchronous by default. Messages are

sent to a destination, and the client doesn’t wait for a reply. But there are times when

it’s useful to be able to wait and get a reply after sending to a destination. One obvious

application is when the JMS destination is a frontend to a service—in this case, a client

sending to the destination would be expecting a reply from the service.

JMS supports this type of messaging by providing a JMSReplyTo header, so that the

receiver knows where to send the reply,

and a JMSCorrelationID, used to match

replies to requests if there are multiple

replies awaiting. This flow of messages is

illustrated in figure 7.5.

Request-reply messaging_sed

Camel takes care of this style of messaging,

so you don’t have to create special

reply queues, correlate reply

messages, and the like. By changing the

message exchange pattern (MEP) to

InOut, Camel will enable request-reply

mode for JMS.

To demonstrate, let’s take a look at an order validation service within Rider Auto

Parts’ backend systems that checks orders against the company database to make sure

the parts listed are actual products. This service is exposed via a queue named validate.

The route exposing this service over JMS could be as simple as this:

from("jms:validate").bean(ValidatorBean.class);

 

When calling this service, you just need to tell Camel to use request-reply messaging by

setting the MEP to InOut. You can use the exchangePattern option to set this as follows:

from("jms:incomingOrders").to("jms:validate?exchangePattern=InOut")...

You can also specify the MEP using the inOut DSL method:

from("jms:incomingOrders").inOut().to("jms:validate")...

With the inOut method, you can even pass in an endpoint URI as an argument, which

shortens your route:

from("jms:incomingOrders").inOut("jms:validate")...

By specifying an InOut MEP, Camel will send the message to the validate queue and

wait for a reply on a temporary queue that it creates automatically. When the ValidatorBean

returns a result that message is propagated back to the temporary reply

queue, and the route continues on from there.

Rather than using temporary queues, you can also explicitly specify a reply queue.

This can be done by setting the JMSReplyTo header on the message or by using the

replyTo URI option described in table 7.5.

A handy way of calling an endpoint that can return a response is by using the

request methods of the ProducerTemplate. For example, you can send a message into

the incomingOrders queue and get a response back with the following call:

Object result = template.requestBody("jms:incomingOrders",

"<order name=\"motor\" amount=\"1\" customer=\"honda\"/>");

This will return the result of the ValidatorBean.

To try this out for yourself, go to the chapter7/jms directory in the book’s source,

and run this command:

mvn test -Dtest=RequestReplyJmsTest

The command will run a unit test demonstrating request-reply messaging as we’ve discussed

in this section.

In the JMS examples we’ve looked at so far, several data mappings have been happening

behind the scenes—mappings that are necessary to conform to the JMS specification.

Camel could be transporting any type of data, so that data needs to be

converted to a type that JMS supports. We’ll look into this next.