I'm processing files with a Camel route like this:
<route>
<from uri="file:inbox?delete=true"/>
<recipientList>
<simple>exec://process.sh?args=inbox/${file:name}</simple>
</recipientList>
<log message="processed ${file:name}: ${body.stdout} ${body.stderr}"/>
</route>
Now I'd like the route to fail when process.sh finishes with nonzero exit-code. I found ${headers.CamelExecExitValue} but don't really know what to do with it.
In the example above, the file should not get deleted when process.sh fails. In my actual use-case, the route consumes files from a JMS queue and I want the file to stay in the queue. I think this can be done with <transacted/> but need to know how to fail the route.
I found How to define exception to be thrown through ref in Apache Camel which in combination with CamelExecExitValue lets me abort this way:
<route>
<from uri="file:inbox?delete=true"/>
<to uri="exec://process.sh"/>
<choice>
<when>
<simple>
${headers.CamelExecExitValue} != 0
</simple>
<throwException exceptionType="java.lang.RuntimeException" message="failed importing ${file:name}: ${body.stdout} ${body.stderr}"/>
</when>
</choice>
<log message="processed ${file:name}"/>
</route>
A bit verbose for my taste but works fine.
So I have the following route (Camel 2.20.0)
I was working on a global <onException> block for a new route. For some reason it wasn't firing, so I moved the items to a doTry/doCatch within one specific route just to play with the error handeling.
<camelContext xmlns="http://camel.apache.org/schema/spring" id="jobfeedCamelContext">
<route id="testError">
<from uri="timer://runOnce?repeatCount=1&delay=5000" />
<doTry>
<throwException exceptionType="java.lang.Throwable"/>
<to uri="errorBean"/> <!-- bean does nothing but explicitly throws java.lang.Throwable -->
<doCatch>
<exception>java.lang.Throwable</exception>
<log message="### exception" />
</doCatch>
</doTry>
<log message="### out of try" />
</route>
</camelContext>
For output I get the stack trace from the beans java.Lang.Throwable (but no stacktrace is generated for the<throwException exceptionType="java.lang.Throwable"/>. I do not get my "### exception" log entry in any scenario, but I do get the "### out of try" log entry.
Have used this functionality in other routes on older version of camel, so I can't really see where I am going wrong. Anyone have any ideas? I've turned on route tracing and there is nothing helpful.
<throwException exceptionType="java.lang.Throwable" message="some text"/>
After upgrading from Camel 2.1 to 2.17 and some code modification we are having some problems with the exception handling in Camel. We send message from app A to app B. The happy flow works fine, but the unhappy flow doesn't.
We send the message to cause an exception but it is not correctly handled in the onexception block.
Actually, we see the following tracelog: ProcessTaskEx - message received, but I don't see: ProcessTaskEx - exception
The exception we get from Camel is:
camel exchange failed without an exception: <SOAP-ENV:Fault xmlns:SOAP-ENV>
Our route looks like this, any idea what the problem could be? Thank you very much for your time community! :)
<?xml version="1.0" encoding="ASCII"?>
<routes xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="switchyard://ProcessTaskEx"/>
<log message="ProcessTaskEx - message received: ${body}" loggingLevel="DEBUG" logName="WebServiceQueues" />
<to uri="switchyard://RequestCapacity"/>
<onException>
<exception>java.lang.Exception</exception>
<exception>webservicequeues.utilities.WebServiceQueueException</exception>
<log message="ProcessTaskEx - exception" loggingLevel="DEBUG" logName="WebServiceQueues" />
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="60000" maximumRedeliveryDelay="900000" retriesExhaustedLogLevel="INFO" retryAttemptedLogLevel="INFO"/>
<handled>
<constant>true</constant>
</handled>
<log message="Failed after Retry.Sending ProcessTask Request to Error Queue" loggingLevel="ERROR" logName="WebServiceQueues" />
<to uri="switchyard://ErrorProcessTaskExQueue"/>
</onException>
</route>
</routes>
As fas as I remember, faults are not handled by default. In order to enable this a property must be set: handleFault="true". It can be set for the whole Camel context or for individual routes.
Example for a route in XML:
<route handleFault="true">
...
</route
In below route , i am using both "try..catch" and onexception features .
If there is any exception in my bean or the lines outside try block..file is moved to ".error" since i used moveFailed option but during exception which are caught by catch block generated by lines of try block,file is lost..
1.when server is down
2.when connection timeout
Please suggest the ways to preserve the file during such failures/exceptions
<camelContext streamCache="false" useMDCLogging="true" id="XXX" xmlns="http://camel.apache.org/schema/spring">
<streamCaching spoolDirectory="/tmp/cachedir/#camelId#/#uuid#" spoolUsedHeapMemoryThreshold="70" bufferSize="65536" anySpoolRules="true" id="myCacheConfig"/>
<onException >
<description>An exception was encountered.</description>
<exception>java.lang.Exception</exception>
<log message="somemessage" loggingLevel="INFO"/>
</onException>
<route >
<from uri="file:D:/Users/Desktop/src?moveFailed=.error" />
<transform>
<method ref="somebean" method="somemethod"/>
</transform>
<doTry>
<to uri="file:D:/Users/Desktop/src" />
<log message="transfered successfully" />
<doCatch>
<exception>java.lang.Exception</exception>
<log message="Exception occurred and Stopping the Route"/>
<to uri="controlbus:route?routeId=XXXX&action=stop"/>
<log message="Stopped the Route:XXX"/>
</doCatch>
</doTry>
</route>
Please suggest the ways to preserve the file during such failures/exceptions
Rethrow the exception in your docatch-block to reach the onException block.
<doCatch>
<exception>java.lang.Exception</exception>
<log message="Exception occurred and Stopping the Route"/>
<to uri="controlbus:route?routeId=XXXX&action=stop&async=true"/> // async=true to resume/finish this route
<log message="Stopped the Route:XXX"/>
<throwException exception="java.lang.Exception"/> // dont know the exact syntax in xml dsl
</doCatch>
I have the onException block below that worked before I upgraded to from camel 2.14 to camel 2.16.1. Before the update, I would get my error caught and printed in the log - "Error posting to MR". After I upgraded to camel 2.16.1, I still get my error in the log, but now, always, my handled error is followed by another timestamp with what appears to be camel default error handler for the error I think I already handled. It looks like this:
"2016-01-26 15:07:09,571 [Camel (mrPostContext) thread #56 - JmsConsumer[mrPost]] ERROR org.apache.camel.processor.DefaultErrorHandler - Failed delivery for (MessageId"....
I don't know if I'm doing something wrong, I tried using java.lang.Throwable instead of java.lang.Exception but so far had no luck. Haven't found anything helpful in documentation yet. As I'm far from being good with camel, I will much appreciate some help.
<route id="mrPost">
<from uri="activemq:mrPost?concurrentConsumers=8" />
<onException>
<exception>java.lang.Exception</exception>
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="1000"/>
<handled>
<constant>true</constant>
</handled>
<to uri="activemq:mr-post-fail" />
<log loggingLevel="ERROR" message="Error posting to MR body:${out.body} exception message: ${exception.message} body:${exception.responseBody}" />
</onException>
<setHeader headerName="CamelHttpMethod">
<constant>PUT</constant>
</setHeader>
<recipientList>
<simple>{{mr.source}}/${headers.id}</simple>
</recipientList>
</route>
Here is a much cleaner solution in case someone is looking for it:
<errorHandler id="loggingErrorHandler" type="LoggingErrorHandler" logName="LoggingErrorHandler" level="OFF"/>
<camelContext id="mrPostContext" trace="false" errorHandlerRef="loggingErrorHandler" >
I think that camel is failing where it puts the message on to the error queue mr-post-fail and is throwing an exception when doing so, hence your exception is propogating to the DefaultExceptionHandler. Since the logging is after the put queue call it is not working as you expected.
If not the case can you give the whole line of the error thats being printed.
"2016-01-26 15:07:09,571 [Camel (mrPostContext) thread #56 - JmsConsumer[mrPost]] ERROR org.apache.camel.processor.DefaultErrorHandler - Failed delivery for (MessageId"..
I got the defaultErrorHandler to collapse with these 2 adjustments:
- set messageHistory="false" on CONTEXT
- set logStackTrace="false" for onException block, like this:
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="1000" logStackTrace="false" />
The timestamp with default error handler still shows up, but much easier on the eye, it looks like this:
2016-02-01 11:26:27,792 [Camel (mrPostContext) thread #262 - JmsConsumer[mrPost]] ERROR org.apache.camel.processor.DefaultErrorHandler - Failed delivery for (MessageId: ID-qn7nwscms01-com-44939-1454025367155-1569-4 on ExchangeId: ID-qn7nwscms01-com-44939-1454025367155-1569-5). Exhausted after delivery attempt: 3 caught: org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://mr.cloud.dig.com/api/contents/news/30939510 with statusCode: 409. Processed by failure processor: FatalFallbackErrorHandler[Pipeline[[Channel[SetHeader(CamelExceptionCaught, Simple: Headers: ${headers} Message: ${exception.message} Body: ${exception.responseBody})], Channel[sendTo(Endpoint[activemq://mr-post-fail])], Channel[choice{when Filter[if: Simple: ${exception.message} not contains "statusCode: 409" do: Pipeline[[Channel[SetHeader(Content-Type, text/plain)], Channel[SetHeader(to, Simple: lw#ac.com)], Channel[SetHeader(subject, Simple: Error posting to MR)], Channel[SetBody(Simple: ${header.CamelExceptionCaught})]]]]}], Channel[Log(mrPost)[Error posting to MR ID: ${headers.contentId}, type:${headers.cmsContentType}, modified:${headers.lastModifiedDate}, getTime:${headers.lastModifiedGetTime}]], Channel[Log(merlinPost)[Error posting to MR body:${out.body} exception message: ${exception.message} body:${exception.responseBody}]]]]]
I hope there is a way to turn it off completely.
I also tried using defaultErrorHandler setup:
<errorHandler id="defaultErrorHandler" type="DefaultErrorHandler">
<redeliveryPolicy logStackTrace="false"/>
</errorHandler>
but it makes no impact.
You can use like the example in this page: http://camel.apache.org/exception-clause.html
<!-- setup our error handler as the deal letter channel -->
<bean id="errorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
<property name="deadLetterUri" value="activemq:mr-post-fail"/>
</bean>
<!-- this is the camel context where we define the routes -->
<!-- define our error handler as a global error handler -->
<camelContext errorHandlerRef="errorHandler" xmlns="http://camel.apache.org/schema/spring">
<route>
<!-- the route -->
<from uri="activemq:mrPost?concurrentConsumers=8" />
<setHeader headerName="CamelHttpMethod">
<constant>PUT</constant>
</setHeader>
<recipientList>
<simple>{{mr.source}}/${headers.id}</simple>
</recipientList>
</route>
</camelContext>
Or, set in rote, to the error handle work only with an specific route
<route errorHandlerRef="errorHandler">
...
</route>
And remove from camelContext