Grails中的Camel异常处理

时间:2016-02-19 15:59:57

标签: grails exception-handling apache-camel

我目前在我的所有路由都继承的抽象类中完成了异常处理。像这样:

    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()

如何在第一个代码段中添加重试代码?我尝试使用嵌套的choice()... when()... otherwise()子句并不断收到编译错误。

任何人都必须做类似的事情吗?

这是我的代码,嵌套的选择().. when().. otherwise()子句:

    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)

2 个答案:

答案 0 :(得分:0)

你必须有2个onException块:

  • 一个onException,其中包含重新传递尝试的重新传递设置
  • 处理异常并发送该电子邮件的另一个onException以及您想要做的事情。
  • 在两个onWhen块上使用onException,根据该http状态代码在任一情况下返回truefalse。 onWhen由Camel执行以了解要使用哪个onException块(您可以使用更多,但首先使用返回true)。

您可以在Camel网站或Camel in Action一书中找到更多详细信息,其中有一章专门介绍错误处理。

答案 1 :(得分: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)