Stop camel route if MQ becomes unavailable - apache-camel

I have one of the camel route as follows, there are many routes.
from("jms:queue:TEST.LQ?transacted=true&connectionFactory=jmsConnectionFactory&cacheLevelName=CACHE_NONE")
.routeId("routeid")
.autoStartup("true")
.transacted("requried")
....
....
I getting below error if TEST.LQ MQ or Queue manager is unavailable.
ERROR [JmsConsumer[TEST.LQ]] [] [o.a.c.c.j.DefaultJmsMessageListenerContainer ] Could not refresh JMS Connection for destination
I tried to handle exception by catching below code, but JmsMessageListenerContainer only throws the message not an exceptiom
onException(MQException.class, JMSException.class)
How stop route if IF MQ is not available?

The camel jms component has the option for this -
Add the testConnectionOnStartup=true option in your from(uri) :
from("jms:queue:TEST.LQ?transacted=true&connectionFactory=jmsConnectionFactory&cacheLevelName=CACHE_NONE&testConnectionOnStartup=true")
This will throw an exception if a connection is not available during startup which can then be handled.
More details are available in the jms-component page

#sree1611,
You can add exceptionListener or errorHandler query parameter in camel jms uri.
To create your own exception listener, implement org.apache.camel.spi.ExceptionHandler
To create your own error handler, implement org.springframework.util.ErrorHandler
I hope errors while consuming from MQ can't be bridged with camel error handlers, so you can't catch JMS exceptions (occurred during message consumption from MQ) in onException().

Related

Camel PAHO routes not receiving offline messages while connecting back

I'm using apache camel xml based paho routes for the subscription, publication process. While online, everything works fine. But I'm not able to receive the offline message.
I have set the following.,
Constant Client ID
Clean Session is FALSE,
Both subscribed & published with QoS 2
With the standalone Program, it's getting all the offline messages. With the camel route it's not happening.
Finally, I was able to solve this one manually.
Camel PAHO Client is not populating the callback function before performing the broker connection. They are doing it only when the connection is made.
So, once the connection is success then the broker just sends all the offline messages. In this case, our client does not have callback handlers to handle these messages. So they are lost.
Other clients (IoThub Client) which uses the PAHO internally is doing it right by setting the callback and initiating the connection.

Camel ProducerTemplate versus Spring JMSTemplate

I am using camel to send message to an IBM MQQueue.
The MDB listening to this queue expects messages of the type com.ibm.jms.JMSMapMessage.
When I use camel producerTemplate, an exception is thrown.
I am doing this
producerTemplate.sendBody("wmq:queue",hashMap);
Exception data: java.lang.ClassCastException: com.ibm.jms.JMSMapMessage incompatible with javax.jms.ObjectMessage
So I tried Spring jmsTemplate, and it worked.
jmsTemplate.send(new MessageCreator() {
#Override
public Message createMessage(Session session)
throws JMSException {
return session.createObjectMessage((Serializable) sctHmap);
}
});
Question:
The jms component documentation says
It uses Spring's JMS support for declarative transactions, including
Spring's JmsTemplate for sending and a MessageListenerContainer for
consuming.
I tried with disabling camels auto conversion using mapJmsMessage=false.
I realised it would not help as it would have sent a hash map, I still got the same exception. Is there any way I can get the producerTemplate to work in the same way as JMSTemplate? ProducerTemplate seems to be more elegant, atleast in terms of my unit tests
It seems I misinterpreted the classcast exception message. Camel was correctly sending, com.ibm.jms.JMSMapMessage, the MDB at the consumer application was expecting javax.jms.ObjectMessage.
I resolved it by setting jmsMessageType=object in the endpoint URI. :)

Camel jms request/reply threading model

I am using camel jms in a synchronous way using request-reply pattern.The camel route exposes a cxf endpoint and it places the message in to the jms queue another component process it and sends the response in replyto queue.
A new thread is getting created while receiving the reply from replyto queue?Iam facing issues with using log4j MDC with in the camel route.The values store in MDC are no more available?
Is it the behaviour of camel jms request/reply pattern?
Below is the JMS endpoint:
<to id="QueueEndpoint" pattern="InOut" uri="hornetq:queue:{{esb.api.requestqueue}}?replyTo=queue:{{esb.api.responsequeue}}&useMessageIDAsCorrelationID=true&replyToType=Exclusive&requestTimeout={{esb.api.queue.requesttimeout}}"/>

Apache camel graceful route shutdown

I have a Camel route which Consumes messages from a Queue and stores the message into a Database. Now I wanted to shut down running camel route manually in a graceful manner. I have a RestEndpoint to be triggered whenever I need to stop Camel route. This endpoint should stop the route. But if there is any in-flight message or transaction running during the shutdown it has to be completed successfully without consuming any new messages from from("") endpoint of camel route and shut down after completing inflight message or transaction. Can anyone help me how Can I code this?
Below are the few options to control/monitor camel routes
CamelContext API's
Control bus component
JMX API's
You can go through below two sites to get started
http://camel.apache.org/controlbus.html
https://dzone.com/articles/apache-camel-monitoring
shutdownRunningTask(ShutdownRunningTask.CompleteCurrentTaskOnly)

Access to routeID in a FTP consumer when connection fails using apache camel

I am using a FTP Endpoint in a Route, and I need to log the route details to database when the connection to ftp fails for some reason, like say a connection timeout or socket timeout. I use a polling strategy, and the rollback method in this strategy gets called on a connection timeout. But the rollback method does not give me access to the RouteID for me to log it to the database.
After doing some reason I found the flag consumer.bridgeErrorHandler which could be set to true to pass the exception to the default error handler. But this just logs the error and doesn't solve my problem of how to get the route details.
Could someone help on how to get access to the routeID in the rollback method, or any other ideas you might have.
I am using apache camel 2.13.4
You could write your own error handler and have custom logic to extract route details. Example:
onException(SocketTimeoutException.class)
.beanRef("myCustomErrorBean", "manageMyError")
public void manageMyError(Exchange exchange) {
CamelContext context = //get this from exchange or inject it via spring or something
context.getRoutes();
//iterate the routes and you can check for the routeIds and anything else you like
}

Resources