Apache Camel onExceptionOccurred component not redelivering as mentioned times - apache-camel

I have an Apache Camel route which invokes restlet component. To better understand what is happening at runtime I also keep the execution state in a database (number of retries, last execution state). I would like to use the redelivery mechanism from the exception handler but which performs some processing on every failure to update my database record.
<bean class="com.tcl.ExceptionOccurredRefProcessor" id="exProc" />
<camelContext errorHandlerRef="eh">
<errorHandler id="eh" onExceptionOccurredRef="exProc"> <redeliveryPolicy
maximumRedeliveries="3" maximumRedeliveryDelay="2000"
retryAttemptedLogLevel="WARN" />
</errorHandler>
<to uri="-------"/> //Invoke rest service
<onException id="_onException1" onExceptionOccurredRef="exProc" useOriginalMessage="true">
<exception>java.lang.Exception</exception>
<handled>
<simple>true</simple>
</handled>
...........
</onException>
</camelContext>
For this I tried to use onExceptionOccurred component with redelivery component and referred on camelContext as in above code but the message got delivered only once and stopped the execution.
Any suggestions please?

First of all: the code you pasted is a bit confusing because there is no Camel route, just a plain to element that cannot be alone in the Camel context.
However, I guess your problem is a "hidden" Camel handling. As documented in the Camel Docs of the Exception Clause, the onException clause overrides the maximumRedeliveries to 0 by default unless you explicitly set the option.
<onException>
<exception>java.lang.Exception</exception> // max. redelivery = 0
</onException>
<onException>
<exception>java.lang.Exception</exception>
<redeliveryPolicy maximumRedeliveries="3"/> // max. redelivery = 3
</onException>
I an not sure about the other redelivery options like maximumRedeliveryDelay, but at least the maximumRedeliveries is overridden if not explicitly set.

Related

doTry/doCatch and global onException behavior

I noticed that after successful doTry/doCatch handling global onException handler is no longer invoked. Here's my sample code:
<doTry>
<to uri="direct:triggerError"/>
<doCatch>
<exception>com.foo.bar.MyException</exception>
<log message="IN DOCATCH"/>
</doCatch>
<doFinally>
<log message="IN FINALLY"/>
</doFinally>
</doTry>
<throwException message="Now handle it in global handler" exceptionType="com.foo.bar.MyOtherException"/>
And in my camel context I have this:
<onException>
<exception>com.foo.bar.MyOtherException</exception>
<handled>
<constant>true</constant>
</handled>
<log message="HANDLING MY OTHER EXCEPTION"/>
<to uri="direct:commonAPIErrorProcessor"/>
</onException>
What I observe is the exception is properly caught in doCatch and doFinally is invoked, but the global onException is never called and I get a stack trace in response. How can I fix it?
I tried it with Camel 3.4.0 and 3.7.0, same results.
The problem in your example is that you call another route within doTry. This seems to confuse the Camel no matter if you use XML or Java DSL (in both DSLs the same effect).
As long as you use simple "statements" in doTry, everything works perfect. When you call another route, it is as you describe very confusing.
Camel catches the exception thrown by the other route, but afterwards the error handler stays "disabled". It seems like Camel loses the doTry scope and therefore never finishes the "error handling disabled state" that is enabled by doTry.
I therefore assume that the "route jump" is not the intended use case for doTry/doCatch. Since it overwrites the normal error handling, it should probably be used only very locally within a route.

Apache Camel - Exception is not catched

I read the corresponding documentation but I couldn't figure out why my Exception is not catched.
This is my route configuration:
<route id="foo">
<from uri="vm://.../>
<doTry>
<to uri="jetty:http://127.0.0.1:123/foo?restletMethod=PUT"/>
<to uri="ejb:java:global/..?method=method1(${body}, ${headers})"/>
<to uri="ejb:java:global/..?method=method2(${body}, ${headers})"/>
<doCatch>
<exception>java.lang.Exception</exception>
<transform>
<simple> ${exception.message} </simple>
</transform>
<to uri="smtp://... />
</doCatch>
</doTry>
</route>
Now when the JettyClient is not reachable a org.apache.camel.CamelExchangeException is thrown,
the route terminates and I receive an email. This is the desired behaviour.
But when method1 throws an exception it is not catched, hence the route continues and
I don't receive an email.
How can I make camel recognize and handle the exception in the second case too?
Solution: Make sure the exception isn't thrown inside a try-catch block -.-
This is stated in the documentation:
http://camel.apache.org/try-catch-finally.html
Camel error handling is disabled
When using doTry .. doCatch .. doFinally then the regular Camel Error
Handler does not apply. That means any onException or the likes does
not trigger. The reason is that doTry .. doCatch .. doFinally is in
fact its own error handler and that it aims to mimic and work like how
try/catch/finally works in Java.
You are probably better off to write it like this:
.doCatch(Exception.class)
// and catch all other exceptions
// they are handled by default (ie handled = true)
.to("direct:error")
In direct:error you can specify what to do in case something goes wrong.

maximumPoolSize in Camel-Netty

I have been playing around with camel-netty and camel-netty-http components, and trying to figure out what the setting maximumPoolSize does.
However, from what i observe based on this is that, the OrderPool always processes 16 concurrent requests. I am trying to change the maximumPoolSize to a value of 5 like the route as below,
<bean id="nettyBean" class="com.redhat.NettyTestImpl">
<property name="message" value="Netty maximumPoolSize test"/>
</bean>
<camelContext trace="false" xmlns="http://camel.apache.org/schema/blueprint" autoStartup="true">
<route>
<from uri="netty-http:http://localhost:8080/hello?maximumPoolSize=5&sync=true"/>
<log message="Forwarding to Netty component ....."/>
<setBody>
<method ref="nettyBean" method="sayHi"/>
</setBody>
<delay>
<constant>3000</constant>
</delay>
<log message="The body contains : ${body}"/>
</route>
</camelContext>
But it seems that i cannot get the maximumPoolSize to set to a value. So, what am i doing wrong ? How can i get the maximumPoolSize set ?
I check this by load testing with 20 concurrent requests and all are processed.
I just checked the code of camel-netty and camel-netty-http, maximumPoolSize is used for the OrderPool, you can use jconsoler to check the thread pool size.
As the OrderPool is used to handle the processor of camel, netty still has the work thread to handle the connection, which means it can still server 20 concurrent request, this time. But the TPS could be just about 5.

Catching exception across camel contexts

I have two routes - each in a different camel context:
<camelContext id="camelContext1" xmlns="http://camel.apache.org/schema/blueprint">
<onException>
<exception>com.me.MyException</exception>
<to uri="log:osgiExecutorLog"/>
</onException>
<route id="MyRoute">
<from uri="amq:test" />
<to uri="direct:MyDirect"/>
</route>
</camelContext>
<camelContext id="camelContext2" xmlns="http://camel.apache.org/schema/blueprint">
<route id="MyRoute">
<from uri="direct:MyDirect" />
<process ref="myProc"/>
</route>
</camelContext>
There are conditions where myProc will throw MyException and I want the onException in camel context 1 to catch that. I tried my luck hard but could not get that to work; is it like catching exceptions across camel contexts not supported or am I missing something?
Instead of trying to throw an exception back to the other context (which may or may not even be possible due to the mechanisms in camel 2.x) you could catch the exception and send a message to some sort of error handling endpoint.
This can be easily defined in a different route builder or context, as long as you know the endpoint name.
Each route then has exactly the same boilerplate exception handler at the top, for example:
onException(Exception.class).handled(true).to("direct-vm:errors")
We routinely use this sort of custom error handling between different route builders (in the same context, but the pattern can apply across contexts just as easily).
In our application, for example, we catch the exceptions, aggregate them in a list, and whenever 15 seconds goes by without a new exception we send an email via smtp - all too easy with a camel route defined as from("direct:errors")...

Stacktrace from Camel Context onException

I'm trying to retrieve the stacktrace from the onException handler in Apache Camel:
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<setHeader headerName="exception">
<simple>${exception}</simple>
</setHeader>
</onException>
However, the above only shows the exception rather than the entire stacktrace.
I understand that Camel stores the caught exception as a property on the Exchange with the key: Exchange.EXCEPTION_CAUGHT, but how can this be retrieved from the camel context routes file ?
Use exception.stacktrace to get the stacktrace. See the variables listed in the table at this page: http://camel.apache.org/simple
<simple>${exception.stacktrace}</simple>
There is also a ${exception.message} to refer to the exception message itself.

Resources