First, I appreciate the ideas:

@Richard -- that could work but it would require that inheritance be in
play. The whole build has to be a subclass of route builder to get it
right. This would be problematic in a situation where you would want to use
different base classes, each with their own helper methods. For example,
imagine creating that base class as a utility in a JAR. Other bases might
contain entirely constructed routes that are parameterized or different
versions of the exception handler. Since we cant multiply inherit in java
we are stuck copying code again.

@Raul -- I don't think that would work because the order of onException
clauses is very important and also is their position in the route. In a
simple test case it might work but the routes we have are extensive.

@All -- I think, after examining the alternatives, that there is some lack
of flexibility in the camel framework that makes it necessary to be a
subclass of RouteBuilder to get everything in position. For example, if you
dig into the route builder class from() methods, you see it does a lot more
than just create a RouteDefinition. To create general utilities is not
going to be a simple matter of just simply instantiating a route definition
and returning it. That leads me to a couple of thoughts.

1) It would be convenient if any part of the route could be swappable by
that part of the definition: i.e. a new method would be created such as:

public ProcessorDefinition onException(final OnExceptionDefinition
definition)

This method would allow you to construct an instance of the definition and
then attach it to the route in the flow:

class MyRouteBuider extends RouteBuilder {
  final OnExceptionDefinition handledToDead =
    new OnExceptionDefinition(Exception.class)
          .useOriginalMessage()
          .handled(true)
          .to("activemq:queue:dead");

 // .. and later

  public void configure() {
    from("activemq:queue:inbox")
     .onException(handledToDead)
     .to("mock:demo_only");
  }
}

This paradigm would be expanded to the whole framework. I would even create
the ability to attach a built up route to the current routes via a simple
method in route builder:

public void attach(final RouteDefinition route);

and in a builder ...

class MyRouteBuider extends RouteBuilder {
  private RouteDefinition createQueueReaderRoute(final String fileName,
final String queueName) {
    // implementation omitted
  }

  public void configure() {
    attach(createQueueReaderRoute("foo.xls", "outbox"));

    // and other routes like normal.
    from("activemq:queue:inbox")
     .onException(handledToDead)
     .to("mock:demo_only");
  }
}

I don't think these things are currently possible (I could be wrong of
course) but they would massively improve the usability of camel from the
point of view of re-use.


*Robert Simmons Jr. MSc. - Lead Java Architect @ EA*
*Author of: Hardcore Java (2003) and Maintainable Java (2012)*
*LinkedIn: **http://www.linkedin.com/pub/robert-simmons/40/852/a39
<http://www.linkedin.com/pub/robert-simmons/40/852/a39>*


On Wed, Apr 2, 2014 at 5:27 AM, Raul Kripalani <[email protected]> wrote:

> Try this technique. Nothing fancy, just a plain old Java static helper
> method. It relies on Camel being able to configure exception handlers if
> placed at the end of the route definition, which I think is possible.
> Please give it a spin and report back to the community!
>
> public class RouteExceptionHandlerEnhancer {
>    public static void enhance(RouteDefinition def) {
>       def.onException(Exception.class).useOriginalMessage().handled(true)
>  // catch exceptions
>                .setHeader(Exchange.FAILURE_ROUTE_ID,
> property(Exchange.FAILURE_ROUTE_ID))    // set route that errored
>                .setHeader(Exchange.EXCEPTION_CAUGHT,
> simple("${exception.stacktrace}"))
> // Store reason for error
>                .to(ExchangePattern.InOnly, endpointAMQ(config.
> queueCaseAutomationDead()))
>           .end();
>    }
> }
>
>
> public class MyRoute extends RouteBuilder() {
>
>     @Override
>     public void configure() throws Exception {
>
>        RouteDefinition route =
>           from("direct:myendpoint")
>               .log("Hello ${body")
>               .to("activemq:queue:foo");
>
>        RouteExceptionHandlerEnhancer.enhance(route);
>
>     }
>
> }
>
> Regards,
>
> *Raúl Kripalani*
> Apache Camel PMC Member & Committer | Enterprise Architect, Open Source
> Integration specialist
> http://about.me/raulkripalani | http://www.linkedin.com/in/raulkripalani
> http://blog.raulkr.net | twitter: @raulvk
>
> On Tue, Apr 1, 2014 at 3:51 PM, kraythe . <[email protected]> wrote:
>
> > Greetings:
> >
> > I have dozens of routes currently in our system and they have one of two
> > variants of the following code:
> >
> >         .onException(Exception.class).useOriginalMessage().handled(true)
> //
> > catch exceptions
> > .setHeader(Exchange.FAILURE_ROUTE_ID,
> property(Exchange.FAILURE_ROUTE_ID))
> > // set route that errored
> > .setHeader(Exchange.EXCEPTION_CAUGHT, simple("${exception.stacktrace}"))
> //
> > Store reason for error
> > .to(ExchangePattern.InOnly,
> > endpointAMQ(config.queueCaseAutomationDead())).end() // to DLQ
> >
> > The problem is I am getting more than annoyed at having to copy paste
> this
> > all over the place but since there are a couple of variants, I cant
> declare
> > a global handler. Making a direct is all well and good but doesnt really
> > buy me much as I still have half the handler on every route.
> >
> > Any ideas how I could reduce code volume here ?
> >
> > *Robert Simmons Jr. MSc. - Lead Java Architect @ EA*
> > *Author of: Hardcore Java (2003) and Maintainable Java (2012)*
> > *LinkedIn: **http://www.linkedin.com/pub/robert-simmons/40/852/a39
> > <http://www.linkedin.com/pub/robert-simmons/40/852/a39>*
> >
>

Reply via email to