Prevent Camel Mail to roll back a message - apache-camel

I have a Apache Camel route that starts with a Mail consumer, followed by some custom processing steps as part of several sub-routes. All routs are connected directly. When some processing fails downstream, the failed exchange returns to the Mail consumer, which performs a rollback and puts the mail message currently being processed back into its original unread state in the inbox:
2022-11-18 16:23:13 WARN MailConsumer:572 - Exchange failed, so rolling back message status: Exchange[7A8EE72E3AFB7CC-00000000000000C0]
This again triggers the Camel mail consumer, resulting in an error loop. I do have a Camel error handler configured for some part of the processing, but not all of it.
How can I configure the mail consumer such that a downstream processing failure does not return the mail back to its unread state?
The mail consumer is configured as follows:
.from("imaps://{{imapPath}}?username={{imapUserName}}&password=RAW({{imapPassword}})&delay={{imapPollingPeriodMs}}&moveTo={{processedMailFolderName}}")

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.

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?

Mule Request Reply: Send Reply After All the Flow Processed

currently I am working with mule. I have 3 flow: RequestFlow, ServiceResponse, and SendResponse.
On the first flow, I processed the request (transform the request parameter, write it into wmq, etc). FYI, wmq on this flow can only be used for write.
On the second flow, I read the response from server via another wmq, transform it into json, and send to VM. FYI, wmq on this flow only can be used for read.
On the third flow, I tried to send back the response to the first flow and generate a file.
To send back the response from flow 3 to flow 1, I try to use request-reply
But, unfortunately, when I tried to send a request, I found out that:
After it reach request-reply component on the first flow, it will directly go to the third flow.
And then, after mule processed all the operation on the third flow, it will send the response back to the request-reply component.
Do some logging (logger component on first flow)
Then, go to the flow, processed all the operation
Processed the third flow again
That's why, after all the process has been finished, my application will:
Generate 2 files (1 contain request xml and 1 contain json response)
Return the request xml to http
However, It's not what I want. The flow that I need is:
Mule processed the operation on first flow until the request-reply component
Go to the second flow and processed all the component
After it finish with second flow, it will goes to third flow. Proceed all the component
Send the reply back to request-reply component on the first flow
Do some logging (logger component in first flow)
And finish
Result from this application should be:
1 File contain JSON response
JSON Response on http
So, how to do so? Thanks in advance.
You don't show the flow that consumes the messages sent to the sender path by the VM outbound endpoint in request-reply: I'm assuming it's a flow that takes care of sending the message to the server.
It seems that all you miss is an VM outbound endpoint in SendResponse that would send the message to the response path, onto which the VM inbound is waiting in the request-reply.
PS. Of course, it's assumed the the server propagates the JMS correlation ID from the request message to the response message, otherwise Mule (nor any client for that matter) could ever reconnect the response to the request and the request-reply would fail.
PPS. You don't need an all router around the single VM outbound endpoint in request-reply.

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

Resources