On 8/9/07, Nick Outram <[EMAIL PROTECTED]> 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");'.
Yeah > 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 processing? e.g. how about this (making a slight change to the language)... onIntercept(anyPredicateGoesHere).to("seda:a").filter(somethingElse).proceed(); from("seda:foo").to("seda:b"); 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... onIntercept(anyPredicateGoesHere).to("seda:a"); from("seda:foo").to("seda:b"); 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? -- James ------- http://macstrac.blogspot.com/