How to setup transaction in Camel JMS Route - apache-camel

How do I setup transaction in JMS route to rollback or not consume a message when an exception occurs. Below is my route. MQ is ActiveMQ.
from("jms:queue:myQueue")
.routeId("myRoute")
.doTry()
.toF("reactive-streams:myStream")
.doCatch(Exception.class)
.process(exchange -> exchange.getFromEndpoint().stop())
.end();`

Simply adding transacted did the job! Also, had to enable connection pooling and camel-jms-starter (for default factories).
from("jms:queue:myQueue?transacted=true")
.routeId("myRoute")
.doTry()
.toF("reactive-streams:myStream")
.doCatch(Exception.class)
.process(exchange -> exchange.getFromEndpoint().stop())
.end();

Related

Stop camel route if MQ becomes unavailable

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().

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)

Camel CXFRS response

camel-fuse 2.8
I have a camel jaxrs server which accepts requests then kicks-off 2 Camel routes.
The first route, consumes requests from cxfrs endpoint/bean and ships them to jms queue inbox.
The second route, consumes requests from jms queue inbox for business logic processing, then ships the results to jms queue outbox.
My question is related to http response and sending the results to jaxrs server consumer.
Is it possible to send an http response back to http client from first route with results from second route? (synchronously)
from("cxfrs:bean:personLookupEndpoint") <-- http client waits for response...
.setExchangePattern(ExchangePattern.InOut)
.process(new RequestProcessor())
.to(inbox);
from(inbox)
.unmarshal(jaxb)
.process(new QueryServiceProcessor())
.to("bean:lookupService?method=processQuery(${body})")
.convertBodyTo(String.class)
.to(outbox); <-- need to send results to font-end consumer synchronously ...
Do you really need to do it using queues? I think that it would be better to use direct: routes instead.
There is a possibility to use the InOut exchange pattern for a JMS endpoint, but it has some limitations: http://fusesource.com/docs/router/2.2/transactions/JMS-Synchronous.html

How to connect an Apache Camel synchronous request/reply endpoint with asynchronous sub-routes

I'd like to route a webservice request to an InOnly endpoint of a jms queue. Then route a response jms message received from a separate InOnly endpoint back to the webservice client as the response. The webservice request/response is a synchronous InOut pattern, and the sub-routes are asynchronous. What options do I have to achieve this with Camel?
The Camel route here is used to explain my question:
String uri={webserice uri}
from(uri)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
ServcieRequest req =
exchange.getIn().getBody(ServcieRequest.class);
// One option to me is to spawn another route here to route to jms queue...
ProducerTemplate template = exchange.getContext().createProducerTemplate();
template.sendBodyAndHeaders("jms:queue:INQueue", req.getPayload(), headers);
// then need to wait ...until received jms response from the route below
}});
from("jms:queue:OUTQueue")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
// received jms response message
// need to update the exchange data in the above route based on jms message
// so the final response to the webservice cilent can receive the data ...
}});
I think you should rely on the request reply mechanism in Camel for this task.
Camel Doc, Exclusive Fixed Reply Queue
So I guess the following DSL route does pretty much what you want (if there is no other reason why you should use a InOnly pattern for the JMS part?). Make sure you tune the requestTimeout if you need (as it defaults to 20Sec timeout).
from(webserviceURI)
.inOut().to("jms:queue:INQueue?replyTo=OUTQueue?replyToType=Exclusive");
Yes, one other thing. If you run this on several nodes, then you need one exclusive queue per node.

Resources