使用HttpEndpoint Options和http4的Apache骆驼

维克托佩

我对骆驼比较陌生。在实现以下功能时,我遇到了这个问题。

要求:调用GET服务,如果响应的状态不是200以外的任何其他状态,则需要抛出HttpOperationFailedException,以便204异常可以在父路由上使用onException进行处理。

我可以使用以下代码实现它:

from("direct:parent")
.onException(HttpOperationFailedException.class)
.onWhen(exchange ->{
    HttpOperationFailedException exe = exchange.getException(HttpOperationFailedException.class);
    if(204 == exe.getStatusCode()){
        return true;
    }
    return false;
})
.setBody(constant(null))
.end()
.to("direct:a");

from("direct:a")
.recipientList("false")
.simple("http4://localhost:8022/test/service?okStatusCodeRange=200-201")
.convertBodyTo(String.class);

但是,使用以下代码时不会引发异常:

from("direct:parent")
.onException(HttpOperationFailedException.class)
.onWhen(exchange ->{
    HttpOperationFailedException exe = exchange.getException(HttpOperationFailedException.class);
    if(204 == exe.getStatusCode()){
        return true;
    }
    return false;
})
.setBody(constant(null))
.end()
.to("direct:a");

from("direct:a")
.to("http4://localhost:8022/test/service?okStatusCodeRange=200-201")
.convertBodyTo(String.class);

任何人都可以解释需要进行哪些更改才能使用它,而不是收件人列表吗?

罗曼·沃特纳

当你从传播的HTTP URI调用direct:parentdirect:a,但保持在一个嵌套的例外条款direct:parent,在抛出的异常direct:a向上传播到父路径。但是,您应该做的是将嵌套异常子句重构为全局异常子句。

我创建了一个简单的测试用例,它可以模拟在204消息上引发的异常,或者可以调用真实服务并在204响应的情况下失败:

import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.http.common.HttpOperationFailedException;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;

public class Http4ExceptionHandlingTest extends CamelTestSupport {

  @Produce(uri = "direct:parent")
  protected ProducerTemplate template;

  @Override
  public boolean isUseAdviceWith() {
    return true;
  }

  @Override
  protected RouteBuilder createRouteBuilder() {
    return new RouteBuilder() {
      @Override
      public void configure() throws Exception {

        onException(HttpOperationFailedException.class)
            .onWhen(exchange -> {
              HttpOperationFailedException
                  exe = exchange.getException(HttpOperationFailedException.class);
              return 204 == exe.getStatusCode();
            })
            .log("HTTP exception handled")
            .handled(true)
            //.continued(true)
            .setBody(constant(null));

        from("direct:parent").routeId("parent")
//            .onException(HttpOperationFailedException.class)
//                .onWhen(exchange -> {
//                  HttpOperationFailedException
//                      exe = exchange.getException(HttpOperationFailedException.class);
//                  return 204 == exe.getStatusCode();
//                })
//                .setBody(constant(null))
//            .end()
            .log("Parent start");
            .to("direct:a")
            .log("Parent done");

        from("direct:a").routeId("a")
            .log("a start")
            .to("http4://localhost:8022/test/service?okStatusCodeRange=200-201")
            .convertBodyTo(String.class)
            .log("a done");
      }
    };
  }

  @Test
  public void testExceptionHandling() throws Exception {
    // comment the following line out if you want to invoke the real service instead!
    weaveRoute();

    context.start();

    Object response = template.requestBody("foo");

    assertThat(response, is(nullValue()));
  }

  @Test
  public void testSuccessfulResponse() throws Exception {
    // comment the following line out if you want to invoke the real service instead!
    weaveRoute();

    context.start();

    Object response = template.requestBody("bar");

    assertThat(response, is(equalTo("bar")));
  }

  private void weaveRoute() throws Exception {
    context.getRouteDefinition("a").adviceWith(context, new AdviceWithRouteBuilder() {
      @Override
      public void configure() throws Exception {
        this.interceptSendToEndpoint("http4*")
            .skipSendToOriginalEndpoint()
            .process(exchange -> {
              String body = exchange.getIn().getBody(String.class);
              if ("foo".equals(body)) {
                Map<String, String> headers = new HashMap<>();
                String location = "";
                HttpOperationFailedException exe =
                    new HttpOperationFailedException("http://bla", 204, "No Content", location,
                                                     headers, "response body");
                throw exe;
              }
            });
      }
    });
  }
}

我在父路由中保留了原始的嵌套异常子句,以便您可以比较结果。全局异常处理程序还有一条额外的.handled(true)`语句,它刚刚超出了当前路由。因此,文档指出以下内容:

如果handle为true,则将处理抛出的异常,并且Camel将不会继续沿原始路由进行路由,而是会中断。但是,您可以在onException中配置一个路由,该路由将被代替使用。如果您需要创建一些返回给调用者的自定义响应消息,或者执行其他任何处理(因为引发了该异常),则可以使用此路由。来源

不将捕获的异常设置为.handled(true)会导致堆栈跟踪的呈现,然后继续执行。

我添加了更多的日志语句以可视化异常处理中的行为。执行上面提供的代码后,您将获得类似以下的输出:

[INFO ] -  - Parent start [            ] [parent] [              ] [main] 
[INFO ] -  - a start [            ] [a] [              ] [main] 
[INFO ] -  - HTTP exception handled [            ] [a] [              ] [main] 

取而代之的是,.handled(true)您也可以使用.continued(true)以便按照记录进行执行:

如果continue为true,那么Camel将捕获该异常,并且实际上只是忽略该异常并继续沿原始路由进行路由。但是,如果在onException中配置了路由,它将先路由该路由,然后再继续在原始路由中路由。

在全局异常子句中启用.continued(true)和禁用测试的情况下运行测试.handled(true)将产生以下日志:

[INFO ] -  - Parent start [            ] [parent] [              ] [main] 
[INFO ] -  - a start [            ] [a] [              ] [main] 
[INFO ] -  - HTTP exception handled [            ] [a] [              ] [main] 
[ERROR] -  - Failed delivery for (MessageId: ...). Exhausted after delivery attempt: 1 caught: null. Handled and continue routing.

Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId              ProcessorId          Processor                                                                        Elapsed (ms)
[parent            ] [parent            ] [direct://parent                                                               ] [         8]
[parent            ] [log9              ] [log                                                                           ] [         0]
[parent            ] [to4               ] [direct:a                                                                      ] [         8]
[a                 ] [log7              ] [log                                                                           ] [         1]
[a                 ] [to3               ] [http4://localhost:8022/test/service?okStatusCodeRange=200-201                 ] [         8]
[                  ] [process2          ] [Processor@0x3c7f66c4                                                          ] [         8]
[a                 ] [log6              ] [log                                                                           ] [         1]
[a                 ] [setBody2          ] [setBody[{null}]                                                               ] [         0]

Stacktrace
--------------------------------------------------------------------------------------------------------------------------------------- [            ] [o.a.c.p.DefaultErrorHandler] [              ] [main] 
org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://bla with statusCode: 204, redirectLocation: 
    at at.erpel.messaginghub.services.unit.routes.rest.Http4ExceptionHandlingTest$2.lambda$configure$1(Http4ExceptionHandlingTest.java:103)
    at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)
    ...
[INFO ] -  - a done [            ] [a] [              ] [main] 
[INFO ] -  - Parent done [            ] [parent] [              ] [main] 

从简化的日志中可以看出,.continued(true)尽管会记录一条消息历史记录以及被忽略异常的堆栈跟踪信息,但不会超出路由范围。

如果父路由中有嵌套异常子句,而子路由确实遇到异常,则在嵌套异常子句中添加.handled(true).continuted(true)无效,因为子路由中捕获的实际异常不会传播到父嵌套异常子句,并且因此根本没有处理。

我已经针对模拟和真实服务测试了代码示例,该真实服务返回了204接收到foo正文的200响应以及接收到其他内容响应。?okStatusCodeRange=200-201因此,在我的情况下配置参数可以按预期工作。对于完整性:我正在使用Camel 2.17.0。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过Https使用基本身份验证的骆驼http4下载文件

来自分类Dev

Vert.x 中的 HttpEndpoint 和代理选项

来自分类Dev

Apache Camel HTTP4和(JSESSIONID)Cookie

来自分类Dev

骆驼Http4 2.12.2:无法从endpointUri推断“ httpClientConfigurer”

来自分类Dev

拥有自己的URI的拥有自己的http4骆驼组件

来自分类Dev

通过蓝图覆盖骆驼http4组件中的默认属性

来自分类Dev

如何设置骆驼HTTP4连接超时选项?

来自分类Dev

通过蓝图覆盖骆驼http4组件中的默认属性

来自分类Dev

apache camel http4错误处理

来自分类Dev

在apache骆驼中使用guice

来自分类Dev

在Apache karaf上捆绑使用Apache骆驼

来自分类Dev

403禁止将wss4jOutInterceptor与骆驼和cxf一起使用

来自分类Dev

具有自签名SSL证书的Apache camel http4

来自分类Dev

使用Apache骆驼,SQL创建CSV文件

来自分类Dev

如何使用Apache骆驼验证XSD?

来自分类Dev

开始使用 apache 骆驼天气库

来自分类Dev

Hazelcast 缓存实现使用 Apache 骆驼蓝图

来自分类Dev

使用骆驼在HTTP上发送普通肥皂

来自分类Dev

如何使用Apache骆驼顺序传输文件(先到先得)

来自分类Dev

使用Apache骆驼观察网络上的反应流

来自分类Dev

我如何在Apache骆驼中使用Elasticsearch 2.2.1

来自分类Dev

在骆驼中使用资源流模拟Camel http端点

来自分类Dev

使用骆驼和activemq“暂停”路线的正确方法是什么?

来自分类Dev

使用骆驼cxfrs和jaxrs服务器之间的区别

来自分类Dev

结合使用杰克逊JSON库和骆驼的异常

来自分类Dev

xalan和saxon同时在apache骆驼上

来自分类Dev

Apache骆驼记录和调试到文件

来自分类Dev

如何使用cxf componnet使用Apache骆驼调用第三方Web服务

来自分类Dev

使用Java为Apache骆驼中的自定义组件配置使用者

Related 相关文章

  1. 1

    通过Https使用基本身份验证的骆驼http4下载文件

  2. 2

    Vert.x 中的 HttpEndpoint 和代理选项

  3. 3

    Apache Camel HTTP4和(JSESSIONID)Cookie

  4. 4

    骆驼Http4 2.12.2:无法从endpointUri推断“ httpClientConfigurer”

  5. 5

    拥有自己的URI的拥有自己的http4骆驼组件

  6. 6

    通过蓝图覆盖骆驼http4组件中的默认属性

  7. 7

    如何设置骆驼HTTP4连接超时选项?

  8. 8

    通过蓝图覆盖骆驼http4组件中的默认属性

  9. 9

    apache camel http4错误处理

  10. 10

    在apache骆驼中使用guice

  11. 11

    在Apache karaf上捆绑使用Apache骆驼

  12. 12

    403禁止将wss4jOutInterceptor与骆驼和cxf一起使用

  13. 13

    具有自签名SSL证书的Apache camel http4

  14. 14

    使用Apache骆驼,SQL创建CSV文件

  15. 15

    如何使用Apache骆驼验证XSD?

  16. 16

    开始使用 apache 骆驼天气库

  17. 17

    Hazelcast 缓存实现使用 Apache 骆驼蓝图

  18. 18

    使用骆驼在HTTP上发送普通肥皂

  19. 19

    如何使用Apache骆驼顺序传输文件(先到先得)

  20. 20

    使用Apache骆驼观察网络上的反应流

  21. 21

    我如何在Apache骆驼中使用Elasticsearch 2.2.1

  22. 22

    在骆驼中使用资源流模拟Camel http端点

  23. 23

    使用骆驼和activemq“暂停”路线的正确方法是什么?

  24. 24

    使用骆驼cxfrs和jaxrs服务器之间的区别

  25. 25

    结合使用杰克逊JSON库和骆驼的异常

  26. 26

    xalan和saxon同时在apache骆驼上

  27. 27

    Apache骆驼记录和调试到文件

  28. 28

    如何使用cxf componnet使用Apache骆驼调用第三方Web服务

  29. 29

    使用Java为Apache骆驼中的自定义组件配置使用者

热门标签

归档