Camel CXFRS response - apache-camel

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

Related

Difference between #JMSListener and #Consume annotations?

I am trying to consume JMS messages sent via spring JmsTemplate using #Consume annotated bean. The consumer is not receiving messages when sent using JmsTemplate.
Whereas, when sent using ProducerTemplate of Camel the messages are received.
What is the difference between #org.springframework.jms.annotation.JmsListener and #org.apache.camel.Consume?
Producer Logic
jmsTemplate.convertAndSend("jms:mailbox", message);
Consumer Logic
#Consume(uri="jms:mailbox")
public void onRequest(String name) {
System.out.println("Received message > "+name);
}
Apache Camel #Consume annotation can consume from any endpoint, which supports consuming. This annotation takes uri as parameter. URI consists of scheme, path and optional params. In case of JMS component the scheme is jms, path is Destination (in your case mailbox) and params are additional options customizing behavior of Consumer.
Spring #JmsListener can consume from JMS and takes Destination as parameter.
Your code does not work because the Destination is mailbox, not jms:mailbox. Spring JmsTemplate does not know about jms scheme, it is Camel specific. So use jmsTemplate.convertAndSend("mailbox", message) on Spring side and #Consume(uri="jms:mailbox") on Camel side.

camel - quartz2 endpoint - Multiple consumers for the same endpoint

I am using apache camel and wants to have multiple routes.The route is as below.
endpoint -> quartz2://tsTimer?cron=0%2F20+*+8-18+%3F+*+MON%2CTUE%2CWED%2CTHU%2CFRI+*&stateful=true&trigger.timeZone=Asia%2FSingapore
Call bean method to get data.
Send to MQ
In this case my route is going to be same as the polling interval is same.
The data from bean method will be different.
And the MQ queue will be same.
Failed to start route route2 because of Multiple consumers for the same endpoint is not allowed: quartz2://tsTimer?cron=0%2F20+*+8-18+%3F+*+MON%2CTUE%2CWED%2CTHU%2CFRI+*&stateful=true&trigger.timeZone=Asia%2FSingapore
How do i achieve this? How do i differentiate camel route in case when the endpoint is quartz2 timer?
I din't notice that in endpoint uri I was having tsTimer which will distinguishes other end-points.
Something like below
quartz2://tsTimer1
quartz2://tsTimer2
quartz2://tsTimer3

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)

Asynchronous request-response across two Netty channels in Camel

I have to integrate with a legacy host that uses TCP/IP communication with separate request and response channels. You send a request to the host on one channel where it is the server, and you need to have a server channel open on which it will send the response some time later. The communication is asynchronous, so there is no guarantee that the next message you receive will be the response to the request you just sent - you have to use a correlation key in the response to tie it back to the request.
I have a Camel route that takes the incoming request and sends it out to the host, and another route that listens for the responses. I have a third route that uses an aggregator to tie the response back to the request using a correlation key. Roughly speaking, the routes look like this:
from("direct:myService")
.process(exchange -> exchange.setProperty("CorrelationKey", exchange.getIn().getBody(MyMessage.class).getCorrelationKey())
.to("netty4:tcp://somehost:555")
.to("direct:aggregate");
from("netty4:tcp://localhost:555")
.process(exchange -> exchange.setProperty("CorrelationKey", exchange.getIn().getBody(MyResponse.class).getCorrelationKey())
.to("direct:aggregate");
from("direct:aggregate")
.aggregate(header("CorrelationKey"), (oldEx, newEx) -> {
if (oldEx == null) {
return newEx;
}
oldEx.getOut().setBody(newEx.getIn().getBody());
oldEx.setProperty(Exchange.AGGREGATION_COMPLETE_CURRENT_GROUP, true)
return oldEx;
}).completionTimeout(5000)
.process(exchange -> logger.log("Received response"));
The aggregation strategy works in the sense that I only see the log message once the response has been processed. The problem is that the request route ("direct:myService") doesn't wait for the aggregation - it has already returned back to the caller. What I want is for that route to block until the aggregation strategy has got the response, so that the message received by the netty4 consumer is used as the out message of the direct:myService route. Is that possible?

Resources