Reputation: 165
How can I catch the final exception that caused the Camel failover load balancer to fail (e.g. to prepare a nice (HTTP) response instead of plain stack trace)?
I have something like this:
from("jetty:http://0.0.0.0:8081/context")
.process(frontendProcessor)
.loadBalance()
.failover(1,
false,
true,
true,
MyFancyException.class)
.to("direct:foo", "direct:bar")
.end()
.process(responseProcessor)
.stop();
with:
from("direct:foo")
.process(potentiallyThrowingMyFancyException);
(and exactly the same for "direct:bar)
Without the load balancing I'd go ahead and use onException
but I can't seem to get my head around how this works nicely with the load balancer and its internal exception handling. On the one hand, I would like to log the stack trace DURING load balancing and on the other hand I want to use onException
to create a nice error response - and ideally both within the same component/implementation.
So I tried this:
onException(Exception.class)
.process(myErrorProcessor)
.handled(true)
.stop();
from("jetty:http://0.0.0.0:8081/context")
.process(frontendProcessor)
.loadBalance()
.failover(1,
false,
true,
true,
MyFancyException.class)
.to("direct:foo", "direct:bar")
.end()
.process(responseProcessor)
.stop();
But handled(true)
seems to break the failover while on the other hand, I assume it's necessary when I use onException
for rendering the final HTTP error response.
How can I distinguish in an onException
error processor between:
an exception occured which triggers the failover, and
the failover load balancer failed entirely and you might want to create a nice final error response for the caller?
Upvotes: 5
Views: 1110
Reputation: 165
I ended up using the same approach as Laurent mentioned in his answer. I'll post the solution to have a complete example but accept his answer.
Please note the single but in my case significant addition to his answer, which is disabling the default error handler.
I had to do the following to achieve what I wanted:
doTry
+doCatch
with rethrow for debug loggingThe routes then look like this.
onException(Exception.class)
.process(myErrorProcessor)
.handled(true)
.stop();
from("jetty:http://0.0.0.0:8081/context")
.process(frontendProcessor)
.loadBalance()
.failover(1,
false,
true,
true,
MyFancyException.class)
.to("direct:foo", "direct:bar")
.end()
.process(responseProcessor)
.stop();
And this:
errorHandler(noErrorHandler());
from("direct:foo")
.doTry()
.process(potentiallyThrowingMyFancyException)
.doCatch(Exception.class)
.process(logAndRethrowProcessor)
.end();
(same for "direct:bar")
Upvotes: 3
Reputation: 478
I'm more of a doTry...doCatch guy myself :-)
You can enclose your loadBalance EIP inside a doTry...doCatch and treat the final exception in there as you see fit. Same for the intermediate exceptions: use doTry...doCatch inside your from("direct:foo") and from("direct:bar") routes and operate on the caught exceptions as you like. Of course, don't forget to rethrow them afterwards.
Upvotes: 2