camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "James Strachan" <>
Subject Re: Exception based routing
Date Thu, 09 Aug 2007 09:27:10 GMT
On 8/9/07, Nick Outram <> wrote:
> James.Strachan wrote:
> > I'm wondering about something like...
> >
> > // lets setup the error handler first
> > onError(MyException.class).maximumRedeliveries(5).onFail().to("seda:c")
> >
> > // now lets do the route
> > from("foo").to("bar");
> >
> > I guess if we define the error handler in the middle of a route we
> > might need some kinda escape expression to go back to the 'real route'
> > from the error handler route. e.g.
> >
> > // this is bad...
> > from("foo").
> >       onError(MyException.class).maximumRedeliveries(5).onFail().to("seda:c").
> >   to("bar"); // by default this would still be part of the error handler
> >
> > maybe something like
> >
> > from("foo").
> >       onError(MyException.class).
> >         maximumRedeliveries(5).onFail().to("seda:c").
> >       onError(Bar.class).
> >         to("seda:d")
> >       onSucccess().
> >         to("bar");
> >
> > i.e. the onError(Class) stuff starts adding an error route for a
> > specific type of exception (which also allows you to configure retry
> > policy & the dead letter destination etc)
> >
> > Thoughts?
> >
> >
> That works too. I particularly like the onError(... construct as it keeps
> the configuration of the error handling maxRedeliveries etc. out of the
> route definition 'from("foo").to("bar");'.


> Not so hot on your second example for the same reason... in-lining the
> onError(... mixes routing semantics with configuration and makes the DSL
> messy.

Agreed - I think defining error handling & interceptors outside of the
route helps readability enormously - and hopefully will encourage the
reuse of error handling/interceptor code across routes; I guess I just
wondered what if folks did want to describe error handling inside a
route & how that could affect the 'grammar' of the DSL.

> It also strikes me that the onError(… approach could be further expanded to
> handle more generalised matches i.e.
> // lets setup the error handler first
> onPattern(error(MyException.class)).maximumRedeliveries(5).onFail().to("seda:c")
> // lets trap any messages with settlement amounts more than £100000
> onPattern(xpath("/settlementAmnt >10000").to("seda:authorisationRequired");
> // now lets do the route
> from("foo").process(new myEnricher()).to("bar");
> The 'onPattern(…' would trap matching messages anywhere on the route at
> 'node' transitions; sort of AOP for routing.

Interesting idea! :)

I guess the onError() is about registering an error handling route
(which in the implementation would hook into the ErrorHandler
implementation to process certain kinds of error using custom routes,
for others the default behaviour kicks in etc).

The onPattern(...) feels more about adding a kind of interceptor
around each processor in the route (which we support now BTW, though
your suggestion is a much nicer DSL for adding them). The error
handling is clear in my mind; since its an exception, the current
route terminates (however deeply nested) and then the error route
kicks in. For the onPattern() AOP thingy; how do we know whether or
not we should continue processing the original route?

i.e. in your example, would it just go to "seda:authorisationRequired"
if the predicate matches or to both destinations?

Am just wondering the semantics of onPattern() really; as when I first
read your suggestion, in my mind I was thinking that onPattern() would
setup an interceptor. So maybe onPattern() needs some kind of
proceed() call in part of its route to indicate if/when it carries on

e.g. how about this (making a slight change to the language)...



i.e. in the above we intercept the route, if the message matches
anyPredicateGoesHere, then its sent to "seda:a" and if somethingElse
matches, then it carries on to "seda:b". So it could go to "seda:a",
"seda:b" or both - depending on the evaluation of the two predicates.

If you really just want it to go to "seda:a" or "seda:b" then you'd just do...



In both cases really, we're just putting Message Filter / Content
Based Router inside an interceptor; rather than in-place inside the
route (and allowing the default behaviour of interceptors to be
inherited on all child nodes of the DSL, so the interceptor would be
applied around all Processors in the chain).

How's that sound?


View raw message