2

Using spring-camel, I have built a route that consumes from a JMS topic (with JMSReplyTo expected to be set for each input message), splits the message into smaller chunks, sends them to a REST processsor, then aggregates the answers and should produce an output message to the destination pointed by JMSReplyTo. Unfortunately, camel implicitly utilises the JMSReplyTo destination in one of the intermediate steps (producing an unmarshalled POJO).

We have a functional requirement to adapt JMSReplyTo in order to provide a request-reply messaging service. I am able to read the JMSReplyTo header before ending the route and I am explicitly converting it to CamelJmsDestinationName, which successfully overrides the destination for JMS component and produces the message on the output topic. I am not sure if this is the best approach and the problem is that camel still utilises the JMSReplyTo on its own.

My RouteBuilder configuration is as follows:

from("jms:topic:T.INPUT")
.process(requestProcessor)
.unmarshal().json(JsonLibrary.Jackson, MyRequest.class)
.split(messageSplitter)
.process(restProcessor)
.aggregate(messagesAggregator)
.unmarshal().json(JsonLibrary.Jackson, BulkResponses.class)
.process(responseProcessor)
.to("jms:topic:recipientTopic");

T.INPUT is the name of the input topic, while recipientTopic is just a placeholder that will be replaced by CamelJmsDestinationName.

I'm not keen on using CamelJmsDestinationName and a sort of a mocked up topic name in route configuration so I'm open to find a better solution. It would be great if camel utilised the JMSReplyTo automatically to produce the output message to the output topic.

Currently, the problem is that camel produces an intermediate output on the JMSReplyTo topic BUT the output is an unmarshalled MyRequest object, which results in an exception saying "ClassNotFoundException: (package name).MyRequest", which is obvious since this is only a class used in my internal processing - I don't want to produce this to the output topic. It seems like Camel does implicitly use the JMSReplyTo destination between requestProcessor and messageSplitter processing... Why? What am I doing wrong? What are the best practices?

genghis
  • 41
  • 6
  • Maybe read the camel JMS component docs: https://camel.apache.org/jms.html – Tim Bish Jun 02 '19 at 16:33
  • I already did and my question still stands. – genghis Jun 02 '19 at 18:16
  • I'm not terribly familiar with Camel so I don't know the answer to your question, but the answer should be somewhere in [here](https://github.com/apache/camel/). – Justin Bertram Jun 03 '19 at 00:05
  • I am searching the answer as well. I think the body is indeed modified, and all your processing is working, but Camel decides to send the original body back to JMSReplyTo. I will share here what can be done if I could find the answer. – WesternGun Dec 20 '22 at 07:39

2 Answers2

0

Use "disableReplyTo=true" in Endpoint. Camel will not try to use any reply option.

Refer: https://camel.apache.org/jms.html for more details

Mohanraj
  • 1
  • 1
  • This is what I did in my tests, so you are right. But my question is why should I disable JMSReplyTo? I want to use it and camel uses it in some way but without my control. I treat disableReplyTo=true and CamelJmsDestinationName as a workaround. Am I wrong? I can't comprehend why should I disable JMSReplyTo when in fact I want to use it? Is this a bug in camel processing? – genghis Jun 04 '19 at 08:02
0

I have found the answer... this is absurdly easy but I haven't seen it anywhere in the documentation.

You just need to call .stop() to mark the route as completed, and Camel will reply the body you configured in the last step to the destination configured in ${header.JMSReplyTo}. It's that simple.

So you can do:

from("jms:my-queue")
    .unmarshall().json(JsonLibrary.Jsonb, InboundMessage.class)
    .bean(SomeProcessingBean.class)
    ....
    .log(LoggingLevel.INFO, "Sending reply to: " + simple("${header.JMSReplyTo}").getExpression().toString())
    .marshall().json(JsonLibrary.Jsonb, ReplyMessage.class)
    .stop();

And you will receive reply.

I wonder why no one has found this before... Nothing when I search the doc or here.... I must be dumb, or the doc is incomplete...but I am not dumb, so.

WesternGun
  • 11,303
  • 6
  • 88
  • 157