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")
Related
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")
Say you have an Application A and an Application B that communicates together using ActiveMQ queues. The communication happens as below.
A sends a request message to application B using the queue name
com.example.requestQueue
B consumes the message request from the queue name com.example.requestQueue
B takes some time to handle the message request and then sends a
response back to B using the response queue
name com.example.responseQueue
A consumes the response message from com.example.responseQueue queue and is done
If application B is always answering, there is no problem.
But if for some reason the application B consumes a message from the request queue com.example.requestQueue and never puts a response message in the response queue com.example.responseQueue, application A will wait forever.
Is there any way to solve this kind of problem please?
NB: The application A is written with Java and Camel and the application B is Written in C++
Thanks.
Camel supports request-reply flows in a single route (exchange pattern InOut), or you can break the request-reply into two separate routes (both exchange pattern InOnly) depending on your use case.
The request-reply patterns have timeout settings available based on the Camel component used. Add the timeout to the Application A Camel route request-reply.
ref: SJMS Component - Newer JMS component
ref: JMS Component - Original JMS component
ref: Request Reply pattern - Info on InOut patterns
Side note--
If Application A is also expected to return something to a caller (ie a web app or a REST/SOAP client), than you would want to make sure you set the messaging response timeout to be lower than than the timeout used by the caller. This allows Application A to return a proper exception/error to the caller before the caller's timeout occurs.
I have configured ActiveMQ redelivery plugin as follows (with max 4 redeliveries)
<redeliveryPlugin fallbackToDeadLetter="true" sendToDlqIfMaxRetriesExceeded="true">
<redeliveryPolicyMap>
<redeliveryPolicyMap>
<defaultEntry>
<redeliveryPolicy initialRedeliveryDelay="5000" maximumRedeliveries="4" redeliveryDelay="10000"/>
</defaultEntry>
</redeliveryPolicyMap>
</redeliveryPolicyMap>
</redeliveryPlugin>
If a client fails to send ACK the message is redelivered. So far so good... However, the max redeliveries are completely ignored by the broker and it keeps redelivering the messages "infinitely" many times. Also the message is never moved to DLQ.
I also tried using:
?jms.redeliveryPolicy.maximumRedeliveries=4 on the connection URI (STOMP Connector), but also with no luck.
Any help is most appreciated!
For a STOMP client I would assume that the broker will not consider the message as being delivered unless the client either ACKs it or NACKs it otherwise it must assume that it never made it to a client and therefore treats it as always having a delivery count of zero. The broker redelivery plugin keys off the message's delivery count so if the message is treated as not having been delivered which in this case it likely is then it will take no action on the message.
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
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}");