2016-02-19 2 views
0

У меня в настоящее время обработка исключений выполняется в абстрактном классе, который наследует все мои маршруты. Что-то вроде этого:Обработка исключений Camel в Grails

onException(SocketException,HttpOperationFailedException) 
     .handled(true) 
     .maximumRedeliveries(settings.maximumRedeliveries) 
     .redeliverDelay(settings.redeliverDelay) 
     .useCollisionAvoidance() 
     .collisionAvoidanceFactor(settings.collisionAvoidanceFactor) 
     .onRedelivery(redeliveryProcessor) 
     .log('retry failed, sending to the route failed coordinator') 
     .to(routeFailedCoordinator) 

Теперь я хочу сделать несколько разных вещей, основанных на разных кодах ответа. Для всех кодов, отличных от 200, вызывается HttpOperationFailedException. Для кодов 4XX я хочу отправить сообщение в неудачную очередь и отправить электронное письмо, если оно включено для этого конкретного маршрута. Для всех других ошибок я хочу пройти цикл повтора. Вот что работает за ошибки 4xx:

onException(HttpOperationFailedException) 
     .handled(true) 
     .process { Exchange x -> 
      HttpOperationFailedException ex = x.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class) 
      log.debug("Caught a HttpOperationFailedException: statusCode=${ex?.statusCode}") 
      ProducerTemplate producer = x.getContext().createProducerTemplate() 
      if (ex?.statusCode >= 400 && ex?.statusCode < 500) { 
       log.debug("Skipping retries ...") 

       producer.send(routeFailedEndpoint, x) 

       x.in.body = "Request:\n${x.in.body}\n\nResponse: ${ex.statusCode}\n${ex.responseBody}".toString() 
       if (sendFailedEmailEnabled) 
        producer.send('direct:routeFailedEmailHandler', x) 
      } else { 
       producer.send(routeFailedRetryEndpoint, x) 
      } 
     }.stop() 

Как добавить код для повтора, как в первом фрагменте коды? Я попытался использовать вложенный выбор() ... когда() ... в противном случае() и продолжал получать ошибки компиляции.

Кому-то приходилось делать что-то подобное?

Вот мой код с вложенным выбором() .. когда() .. в противном случае() положения:

onException(HttpOperationFailedException) 
     .handled(true) 
     .choice() 
      .when { Exchange x -> 
       HttpOperationFailedException ex = x.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class) 
       log.debug("Caught a HttpOperationFailedException: statusCode=${ex?.statusCode}") 
       if (ex?.statusCode >= 400 && ex?.statusCode < 500) { 
        log.debug("Skipping retries ...") 
        x.in.body = "Request:\n${x.in.body}\n\nResponse: ${ex.statusCode}\n${ex.responseBody}".toString() 
        return true // don't retry 
       } 

       log.debug("Performing retries ...") 
       return false // do attempt retries 
      }.choice() 
       .when { !sendFailedEmailEnabled }.to(routeFailedEndpoint) 
       .otherwise() 
        .multicast().to(routeFailedEndpoint, 'direct:routeFailedEmailHandler').endChoice() 
      .otherwise() 
       .getParent().getParent().getParent() 
       .maximumRedeliveries(settings.maximumRedeliveries) 
       .redeliverDelay(settings.redeliverDelay) 
       .useCollisionAvoidance() 
       .collisionAvoidanceFactor(settings.collisionAvoidanceFactor) 
       .onRedelivery(redeliveryProcessor) 
       .to(routeFailedCoordinator) 

ответ

0

Вы должны иметь 2 OnException блоков:

  • Один onException с параметры повторной доставки для попыток повторной доставки
  • Другой onException, который обрабатывает исключение и отправляет это письмо и что вы хотите сделать.
  • Используйте onWhen на обоих блоках onException, чтобы вернуть true или false в любой ситуации на основе этого кода состояния http. OnWhen выполняется Camel, чтобы узнать, какой из блоков onException использовать (вы можете иметь больше, но сначала использовать true).

Более подробную информацию вы найдете на веб-сайте Camel или в книге Camel in Action, в которой содержится полная глава, посвященная обработке ошибок.

+0

Спасибо, Клаус. Я сделаю снимок. – emiles

0

Спасибо, Клаус, ты указал мне в правильном направлении.

В принципе, как сказал Клаус, использовать несколько блоков OnException, каждый использует onWhen пункт ...

onException(HttpOperationFailedException) 
     .onWhen(new Predicate() { 
      public boolean matches(Exchange exchange) { 
       HttpOperationFailedException ex = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class) 
       log.debug("Caught an HttpOperationFailedException: statusCode=${ex?.statusCode}, processing 4XX error") 
       return (ex?.statusCode >= 400 && ex?.statusCode < 500) 
      } 
     }).handled(true) 
      .to(routeFailedEndpoint) 
      .choice() 
       .when { sendFailedEmailEnabled }.process(prepareFailureEmail).to('direct:routeFailedEmailHandler') 

    onException(HttpOperationFailedException) 
     .onWhen(new Predicate() { 
      public boolean matches(Exchange exchange) { 
       HttpOperationFailedException ex = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class) 
       log.debug("Caught an HttpOperationFailedException: statusCode=${ex?.statusCode}, processing >=500 error") 
       return (ex?.statusCode >= 500) 
      } 
     }).handled(true) 
      .maximumRedeliveries(settings.maximumRedeliveries) 
      .redeliverDelay(settings.redeliverDelay) 
      .useCollisionAvoidance() 
      .collisionAvoidanceFactor(settings.collisionAvoidanceFactor) 
      .onRedelivery(redeliveryProcessor) 
      .to(routeFailedCoordinator)