Camel route - get JMSMessageId after sent - java

How can I get JMSMessageID in camel route producer (with Spring context),
JMSMessageID needs to be generated by MQ server, like it works with native JMS.
In the camel's documentation
JMSMessageID is in section "consumer",
"Camel adds the following JMS properties to the In message headers when it receives a JMS message",
but I need it from producer side after send.
I can's use tmpReply queue with camel's InOut.
I suppose, I need to use MessagePostProcessor, or MessageSentCallback, but I don't know how.
Thanks a lot!

This works for me:
from("someRoute")
.to("jms://OUTPUT.QUEUE?includeSentJMSMessageID")
.log("JMSMessageID = ${header.JMSMessageID}");

Related

Set ReplyToQMgr and ReplyToQ in Apache Camel reout to receive COA using IBM MQ

I am using Apache Camel and IBM MQ to send messages. I need to receive COA when a message gets delivered to a remote queue. The general picture looks like this:
When the message reaches msg_q2 queue, I should receive the COA back. So, the problem is that I am not able to set the QMGR_REM as reply-to queue manager, which is supposed to produce COA.
https://www.ibm.com/docs/en/ibm-mq/8.0?topic=messages-reply-queue-queue-manager
I tried setting JMS_IBM_MQMD_xxx headers, but for some reason those headers either get omitted or ignored (by Camel?), and the message fails to be put on the queue with the reason that the reply-to queue is not specified. Also, I tried setting JMSReplyTo header as queue://reply-to-qmgr/reply-to-q. In this case the queue:// part gets removed, and the rest is simply set as a reply-to queue name.
I am relatively new to Apache Camel, and IBM MQ, so any input would be very appreciated. Thank you in advance!
In your application, just provide the name of your ReplyToQ as replyToQ1 and leave the ReplyToQMgr field blank. The queue manager will fill it in with the local queue manager name QMGR_LOC for you.
And on QMGR_REC do one of the following:-
If your transmission queue for the channel from QMGR_REM to QMGR_LOC is named exactly QMGR_LOC, you have nothing further to do. When QMGR_REM comes to put the COA onto queue replyToQ1 on queue manager QMGR_LOC, it will resolve it to the transmission queue that has the name QMGR_LOC and the channel will deliver it.
If your transmission queue for the channel from QMGR_REM to QMGR_LOC is not named exactly QMGR_LOC, then make the following definition on QMGR_REM:
DEFINE QREMOTE(QMGR_LOC) RNAME(' ') RQMNAME(QMGR_LOC) +
XMITQ(your-transmission-queue-going-to-QMGR_LOC)
So, basically by trial and error I figured out that adding mdWriteEnabled=true property onCamelJmsDestinationName Camel header made it working as I need.
The code is something like this:
route.setHeader("CamelJmsDestinationName", "queue:///msg_q1?targetClient=1&mdWriteEnabled=true")
Then I set reply-to queue manager via MQMD property
route.setHeader("JMS_IBM_MQMD_ReplyToQMgr", "QMGR_REM")
and reply-to queue
route.setHeader("JMSReplyTo", "replyToQ2")

how to retrieve RFH message headers from a message coming from MQ?

Can anyone please help me in retrieving message headers from the message coming from Websphere IBM MQ ?
We are using JMS OnMessage method to browse the MQ and the type of message received from MQ is "BytesMessage". We want to iterate through the RFH message headers and collect them.
We have tried using MQHeaders to iterate over the MQMessage but could not as it was throwing an exception.
Please advice me.
a good place to start reading is https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q031990_.htm which explains how IBM MQ implements JMS.
Next you should print out your received JMS Message with toString() or iterate through your properties and check the properties you receive. Depending on RFH or RFH2 you will see different fields.
You can find explanations for these fields in https://www.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q032000_.htm
and https://www.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q032060_.htm

JMS component - ConnectException for InOut pattern

I have a problem using the Apache Commons JMS component. If I use InOut exchange pattern to put the message in the queue and the JMS Server is down, I receive the java.net.ConnectException with recovery attempts being made every 5000 ms. I assume that Camel implicitly creates a consumer endpoint to listen to the replyTo queue, so I'm not sure if it's possible to disable this behavior.
Is there a way to disable the recovery in this case?
Below is a camel groovy route. Hope it solves your problem.
from("jms:queue:TEST?disableReplyTo=true")
.setExchangePattern(ExchangePattern.InOut)
/*Do Processing*/
.inOnly("jms:queue:TEST")
Because the current Message Exchange Pattern is InOut the JMS Component expects a reply message. If you would like to send a "fire-and-forget" message to JMS component you need to change the MEP first to InOnly.
Example:
.to(ExchangePattern.InOnly, "activemq:somequeue")

Camel route sourced from seda is not routing to the Kafka destination endpoint

I have a simple camel route which consumes from a Kafka topic. Does some processing and writes back to another kafka topic.
I needed to do some processing in between . I used seda in the route so that the kafka consumer doesn't get blocked on processing.
But after processing, Camel routes the message back to the source kafka endpoint and not to the destination endpoint.
from("kafka:<source endpoint details>")
.routeId("FromKafka")
.log("########: ${body}")
.to("seda:myseda?waitForTaskToComplete=Never");`
from("seda:myseda")
.routeId("sedaRoute")
.process(myprocessor)
.to("kafka:<destination endpoint details>"
The output payload is once again put in the source kafka topic. If I just replace seda with direct, it just works fine.
from("kafka:<source endpoint details>")
.routeId("FromKafka")
.log("########: ${body}")
.to("direct:mydirect");`
from("direct:mydirect")
.routeId("sedaRoute")
.process(myprocessor)
.to("kafka:<destination endpoint details>"
I suspected Kafka might be a request-reply exchange and the response is given back to the source endpoint. Hence tried adding "waitForTaskToComplete=Never" to seda. But no success.
Any help will be much appreciated.
I think you need to set the exchange pattern to "in only".
Like this:
.to(ExchangePattern.InOnly,"seda:myseda")
Incase your kafka consumer and producer topics are different. Apache camel by default keeps the consumer headers for producer as well .To avoid this, use have the update the kafka headers topic. Can we done using , bridgeEndpoint option for producer. If the option is true, then KafkaProducer will ignore the KafkaConstants.TOPIC header setting of the inbound message. Or u can directly set headers of KafkaConstants.TOPIC for producer.
This happens only for seda routes. works perfectly fine with direct route

Spring Integration - How to create the adapters programmatically?

I am implementing spring-integration based application where i need to send messages (POJO) to ActiveMQ queues dynamically (based on message params). What is the best way to implement this using spring integration concepts ?
E.g., The request message (id:123, processor:ABC) should be sent to ABC.REQUEST queue and response message should be received from ABC.RESPONSE queue. Similarly the request message (id:456, processor:XYZ) should be sent to XYZ.REQUEST queue and response message should be received from XYZ.RESPONSE queue.
You don't need to programmatically create them programmatically, you can use dynamic destinations.
See request-destination-expression and reply-destination-expression in the documentation.
Something like...
request-destination-expression="payload.processor + '.REQUEST'"
reply-destination-expression="payload.processor + '.RESPONSE'"
...should do it.

Categories