Grails中的Camel异常处理

Grails中的Camel异常处理,grails,exception-handling,apache-camel,Grails,Exception Handling,Apache Camel,我目前在所有路由继承的抽象类中进行异常处理。大概是这样的: onException(SocketException,HttpOperationFailedException) .handled(true) .maximumRedeliveries(settings.maximumRedeliveries) .redeliverDelay(settings.redeliverDelay) .useCollisionAvoida

我目前在所有路由继承的抽象类中进行异常处理。大概是这样的:

    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 get。对于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()
OneException(HttpOperationFailedException)
.已处理(正确)
.进程{Exchange x->
HttpOperationFailedException ex=x.getProperty(Exchange.EXCEPTION\u已捕获,HttpOperationFailedException.class)
log.debug(“捕获到HttpOperationFailedException:statusCode=${ex?.statusCode}”)
ProducerTemplate producer=x.getContext().createProducerTemplate()
如果(ex?.statusCode>=400&&ex?.statusCode<500){
调试(“跳过重试…”)
producer.send(routeFailedEndpoint,x)
x、 in.body=“请求:\n${x.in.body}\n\n响应:${ex.statusCode}\n${ex.responseBody}.toString()
如果(sendFailedEmailEnabled)
producer.send('direct:routeFailedEmailHandler',x)
}否则{
producer.send(routeFailedRetryEndpoint,x)
}
}.停止
如何像在第一个代码段中那样添加重试代码?我尝试使用嵌套的choice()…when()…otherwise()子句,但不断出现编译错误

有人必须做类似的事情吗

下面是我的代码,其中包含嵌套的choice()…when()…otherwise()子句:

OneException(HttpOperationFailedException)
.已处理(正确)
.choice()
。当{Exchange x->
HttpOperationFailedException ex=x.getProperty(Exchange.EXCEPTION\u已捕获,HttpOperationFailedException.class)
log.debug(“捕获到HttpOperationFailedException:statusCode=${ex?.statusCode}”)
如果(ex?.statusCode>=400&&ex?.statusCode<500){
调试(“跳过重试…”)
x、 in.body=“请求:\n${x.in.body}\n\n响应:${ex.statusCode}\n${ex.responseBody}.toString()
返回true//不重试
}
调试(“执行重试…”)
返回false//do尝试重试
}.choice()
.when{!sendFailedEmailEnabled}.to(routeFailedEndpoint)
.否则()
.multicast().to(routeFailedEndpoint,'direct:routeFailedEmailHandler')。endChoice()
.否则()
.getParent().getParent().getParent()
.maximumRedeliveries(设置.maximumRedeliveries)
.RedeliveDelay(设置.RedeliveDelay)
.UseCollisionAvoidation()的用法
.collisionAvoidanceFactor(设置.collisionAvoidanceFactor)
.OnRetelivery(重新交付处理器)
.to(路由文件协调器)

您必须有2个OneException块:

  • 一个
    onException
    ,具有用于重新交付尝试的重新交付设置
  • 另一个
    onException
    ,处理异常并发送电子邮件和您想要做的事情
  • 在两个
    onException
    块上使用
    onWhen
    ,根据http状态代码在两种情况下返回
    true
    false
    。onWhen由Camel执行,以知道要使用哪一个onException块(可以有更多块,但首先要返回true)

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

谢谢,克劳斯,您为我指明了正确的方向

基本上,正如克劳斯所说,使用多个OneException块,每个块使用一个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)
OneException(HttpOperationFailedException)
.onWhen(新谓词(){
公共布尔匹配(Exchange){
HttpOperationFailedException ex=exchange.getProperty(exchange.EXCEPTION\u已捕获,HttpOperationFailedException.class)
log.debug(“捕获到HttpOperationFailedException:statusCode=${ex?.statusCode},正在处理4XX错误”)
返回(ex?.statusCode>=400&&ex?.statusCode<500)
}
}).已处理(正确)
.to(路由指定点)
.choice()
.when{sendFailedEmailEnabled}.process(prepareFailureEmail).to('direct:routeFailedEmailHandler'))
OneException(HttpOperationFailedException)
.onWhen(新谓词(){
公共布尔匹配(Exchange){
HttpOperationFailedException ex=exchange.getProperty(exchange.EXCEPTION\u已捕获,HttpOperationFailedException.class)
log.debug(“捕获到HttpOperationFailedException:statusCode=${ex?.statusCode},处理>=500错误”)
返回(ex?.statusCode>=500)
}
}).已处理(正确)
.maximumRedeliveries(设置.maximumRedeliveries)
.RedeliveDelay(设置.RedeliveDelay)
.UseCollisionAvoidation()的用法
.collisionAvoidanceFactor(设置.collisionAvoidanceFactor)
.OnRetelivery(重新交付处理器)
.to(路由文件协调器)

谢谢你,克劳斯。我要试一试。
    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)