camel control not reaching doFinally in case of exception - apache-camel

In below camel route there is try and finally block in spring DSL, the control doesn't reaches finally block in case there is 404 Http status code returned.Why is this happening as the expectation is that the finally block should get executed irrespective of any expection or errors in try block.The response returned is :org.apache.camel.component.http.HttpOperationFailedException: HTTP operation failed invoking localhost:8080/testUri
<camel:doTry>
<from uri="http://localhost:8080/testTry"/>
<!-- Non existence service called below returns 404 Exception-->
<to uri="http://localhost:8080/testUri" />
<camel:doFinally>
<to uri="log:inFinally" />
</camel:doFinally>
</camel:doTry>
Update i tried to throw an exception in the try block and even this exception was thrown and returned in response and call in finally block not executed at all.

This is because you have to handle the exception somewhere in your application. If the exception is thrown all the way to the camel context and isn't handled there, the routing of that exchange stops and the doFinally never occurs.

Related

Camel appears to ignore onException instruction - what am I doing wrong?

I have a Camel (2.21.2) route that gets an XML file via FTP and then splits it before processing further, somewhat like...
from("direct-vm:start")
.split()
.xtokenize("*/row", 'w', ns)
.streaming()
...
If an empty file is passed, I am getting a com.ctc.wstx.exc.WstxEOFException raised by the xtokenize step I presume, which seems perfectly reasonable.
However, when I try to put in an onException clause, it doesn't seem to be catching the exception.
I have:
onException(com.ctc.wstx.exc.WstxEOFException.class)
.handled(true)
.log(org.apache.camel.LoggingLevel.INFO,
"myLogger",
"File ${header.CamelFileName} is empty or invalid XML");
and yet the exception is resulting in the route failing with the exception, and my handler log message is never produced.
However, if I change the onException clause to java.lang.Exception.class, it does handle the exception.
I don't want this to handle any exception, just the one caused by an empty or incomplete file.
What I am doing wrong here? How do I get onException to handle only the exception I am interested in?
Thanks for looking!

Apache Camel NotifyBuilder not working as expected

I am trying to test an error handling route. The NotificationBuilder does not work as expected (it always returns false).
Created a main route and a test route to test the main route. I used Spring Boot - all other tests work fine, so there is no problem with the setup I guess.
errorHandler(deadLetterChannel("seda:errorQueue").maximumRedeliveries(5).redeliveryDelay(1000));
from("file://{{inputFolder}}?delay=10s&noop=true")
.routeId("InputFolderToTestSedaRoute")
.setHeader("myHeader", constant("MY_HEADER_CONSTANT_VALUE"))
.to("seda://testSeda")
.log(LoggingLevel.DEBUG, "**** Input File Pushed To Output Folder *****");
There is an error route too.
from("seda:errorQueue")
.routeId("ErrorHandlingRoute")
.log("***** error body: ${body} *****")
.log("***** Exception Caught: ${exception} *****");
I then used adviceWith() to throw an Exception in the main route.
Then created the NotifyBuilder.
NotifyBuilder errorRouteNotifier = new NotifyBuilder(camelContext)
// .wereSentTo("seda:errorQueue")
.fromRoute("ErrorHandlingRoute*")
.whenReceived(1)
.create();
Then I sent message using ProducerTemplate. But when I test the match condition, it always fails.
boolean done = errorRouteNotifier.matches(5, TimeUnit.SECONDS);
assertTrue("Should have thrown Exception and caught at errorQueue", done);
But the message is routed to the ErrorHandlingRoute as I can see the messages (body and exception) I asked to print there.
Please let me know what is the issue here. Thanks in advance.

Exchange body substring in log message

How to log exchange body substring as message attribute of log component?
I have tried these:
<log message="SEND RESPONSE TO WEB SERVICE: Headers:[${headers}]\nBody:[${bodyAs(String).substring(0,1000)}]"/>
<log message="SEND RESPONSE TO WEB SERVICE: Headers:[${headers}]\nBody:[${body.toString().substring(0,1000)}]"/>
but none works. First variant is marked as mistake by IDE Camel plugin and does not allow application to start, and the second one throws the exception about calling toString() at null (although body is not).
ps body is really instance of String.
Read this page, particularly the section "Full Customization of the Logged Output"

Having access to entire soap:body when service call returns soap:fault

I'm building a route that sends a SOAP request to a webservice. For achieving that, I wrote this code.
.doTry()
.inOut(getEndpointDocumentWS())
.log("Response WHEN OKAY: ${body}")
.process(Document_WS_REPLY_PROCESSOR)
.endDoTry()
.doCatch(Exception.class)
.log(LoggingLevel.INFO, "SOAP REPLY WITH FAULTMESSAGE")
.log("Response ON ERROR FAULT: ${body}")
.process(Document_WS_REPLY_ERROR_PROCESSOR)
.end();
Everything goes as planned when the service response is "okay". Otherwise, when the service response is a soap:Fault, I'm not having access to all of the response (I am using soapUI to mock the soap:Fault response).
I can access a tiny fraction of the soap:fault by getting the EXCEPTION_CAUGHT property.
The instruction
.log("Response ON ERROR FAULT: ${body}")
Has no data at all.
What can I do differently to have access to all the instead of only the faultstring?
Exception exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT,
Exception.class);
According to this answer, Camel's CXF component not catching onException(Exception.class):
Camel's onException only triggeres if there is an exception. A SOAP
Fault is represented as a Message with the fault flag = true.
What you can do is to set handleFault=true on CamelContext, then it
will turn SOAP fault messages into an exception that the onException
can react upon.
Assuming you have not configured handleFault=true, then it's odd that your exception handler is running at all. It could be that some other exception, not the Fault you're looking for, is occurring which causes the exception handler to run.
If you have already configured handleFault=true, I don't have any advice except inspect the data objects in a debugger to see if you can find out what's going on. (If you don't know, to do this you can add a Processor to your exception handler and insert a break point inside the Processor. Break points don't work in route definition because route definitions are only run on initialization.)

Camel onException redelivery Clarification

So I'm a little unsure of how this will work. I have a "Broken Pipe" Exception that occurs every now and then. It triggers 2 exceptions to be thrown (according to the log): org.apache.camel.component.file.GenericFileOperationFailedException due to the file not being able to reach its endpoint and java.net.SocketException because that is the root cause of why the file wasn't able to reach the endpoint.
So to deal with that I have an an <onException> block that looks like this:
<onException>
<exception>org.apache.camel.component.file.GenericFileOperationFailedException</exception>
<exception>java.net.SocketException</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="5000"/>
</onException>
So from what I understand Camel should select the GenericFileOperationFailedException and then try to perform 2 Redeliveries, 5000 milliseconds apart.
Well then what happens if it is unable to redeliver in those 2 attempts, will Camel then select the SocketException due to the nature of the error thrown?
Meaning Camel will attempt 4 total redeliveries, taking up a total of 20000 milliseconds?
Camel will initially select on based on the order you have written them. "..the order in which the onException is configured takes precedence. Camel will test from first...last defined."
Straight from the documentation:
So if an exception is thrown with this hierarchy:
+ RuntimeCamelException (wrapper exception by Camel) + OrderFailedException
+ IOException
+ FileNotFoundException
Then Camel will try testing the exception in this order:
FileNotFoundException, IOException, OrderFailedException and
RuntimeCamelException. As we have defined a
onException(IOException.class) Camel will select this as it's the
closest match.
So based on the example, I would assume that
SocketException
will get triggered and redelivery started because it has an exact match and it is lower down in the stacktrace which Camel starts finding matches from.

Resources