【问题标题】:Camel REST service throws Exception when returning nullCamel REST服务返回null时抛出异常
【发布时间】:2017-03-10 15:22:41
【问题描述】:

我有一个简单的 REST 服务。有客户,我可以通过其 ID 获得客户。如果没有具有请求 ID 的客户端,则应返回 404 未找到。

以下是相关部分:

rest("/client")
    .consumes("application/json").produces("application/json")
    .get("{id}")
        .to("direct:getClient");

from("direct:getClient")
    .bean(clientService, "getClient(${header.id})")
     .choice()
        .when(simple("${body} == null"))
            .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(404));

可以找到客户端时一切正常,但是,当找不到客户端并且 clientService 返回 null 时,我得到以下堆栈跟踪:

org.apache.camel.RuntimeCamelException: java.io.IOException: Stream closed
    at org.apache.camel.http.common.HttpMessage.createBody(HttpMessage.java:74)
    at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:47)
    at org.apache.camel.processor.CamelInternalProcessor$StreamCachingAdvice.after(CamelInternalProcessor.java:799)
    at org.apache.camel.processor.CamelInternalProcessor$StreamCachingAdvice.after(CamelInternalProcessor.java:767)
    at org.apache.camel.processor.CamelInternalProcessor$InternalCallback.done(CamelInternalProcessor.java:246)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:573)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197)
    at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:62)
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:542)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:120)

我想不出来这个。从 bean 方法调用返回 null 应该是可能的,对吧?

【问题讨论】:

  • 您使用什么 Camel 版本?你使用什么 Camel 组件和 rest-dsl 作为 HTTP ?
  • 2.18.0 和camel-servlet
  • 好的... 2.18.0 中似乎有一个错误。我降级到 2.17.3,它工作正常。这是一个严重的问题,我会创建一个测试并报告它。
  • 我发现了错误并记录了一张票:issues.apache.org/jira/browse/CAMEL-10425
  • 啊,谢谢!我打算今天这样做:)

标签: java rest exception apache-camel http-status-code-404


【解决方案1】:

尝试作为解决方法使用

.setBody().method(clientService, "getClient(${header.id})")

我怀疑它的 .bean() 当您返回 null 值作为新消息体时有一个小错误,这会欺骗底层 HttpMessage 认为消息体尚未初始化,并且因此,再次读取流时会出现流错误。

【讨论】:

  • 确实有道理。但是,它也不起作用,但错误略有不同:“org.apache.camel.language.bean.RuntimeBeanExpressionException:无法调用方法:getClient(${header.id}) on null 由于:org. apache.camel.RuntimeCamelException:java.io.IOException:流已关闭”。此消息似乎表明 clientService 为 null('on null'),但绝对不是这种情况,因为当 getClient 返回非 null 结果时一切正常。
【解决方案2】:

我认为如果在您的 bean 中找不到 clientid 并在休息路线中处理,您可以抛出新异常 SomeClassException 的主要思想

public class SomeClassException  extends Exception {
    private static final long serialVersionUID = 2542653496302641967L;    
    public SomeClassException() {
    }    
    public SomeClassException(String arg0) {
        super(arg0);
    }
}

您的路线:

                rest("/client/")
                .consumes("application/json").produces("application/json")
                .get("{id}")
                    .to("direct:getClient");

                onException(SomeClassException.class) .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(404)).handled(true);

                from("direct:getClient")
                .bean(clientService, "getClient(${header.id})")
                ;

【讨论】:

    【解决方案3】:

    我在路由上返回 NO_CONTENT 时遇到了类似的问题,该方法可以选择返回对象或不返回对象,具体取决于是否有任何队列。代码结构如下:

    rest("/foo")
        .get("/bar").route().to("direct:foo").endRest()
    ;
    
    from("direct:bar")
        .process(exchange -> {
            // ... service calls that eventually resulted in this ...
            //       (status code of 204 and a body of null)
            ResponseEntity responseEntity = 
    exchange.getIn().getBody(ResponseEntity.class);
            exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, responseEntity.getStatusCodeValue());
            exchange.getIn().setBody(responseEntity.getBody());
        })
        .marshal().json(JsonLibrary.Jackson)
    ;
    

    我遇到了同样的错误,org.apache.camel.RuntimeCamelException: java.io.IOException: Stream closed,尽管我正在单步执行我的代码并看到一切都按预期进行。和你一样,当方法返回一个对象时一切正常,但只有在 body 设置为 null 时才抛出这个异常。

    此时,我认为当响应正文设置为null 时,Camel 中存在一些复杂的事件系列会出错。单步执行代码并没有我希望的那么有用,所以我只是查看了NO_CONTENTNOT_FOUND 的响应实体的标准做法,并偶然发现了this post。我相信 Camel 与转换器的工作方式相同,并且需要某种类型的对象,所以我只是像这样修改了我的代码:

    exchange.getIn().setBody(responseEntity.getBody() == null ? "" : responseEntity.getBody());
    

    结果返回给客户端的消息中仍然没有正文,也没有IOException: Stream closed错误。

    【讨论】:

      【解决方案4】:

      只是为了添加一个特定的场景,当引发类似错误时,根本原因是无效的 Json。

      考虑这个具体的例子:

       String tempDate = yourExchangeObject.getIn().getBody(String.class);
       JSONObject inputJson = new JSONObject(tempDate); //Exception
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-22
        • 2012-06-08
        • 2018-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        相关资源
        最近更新 更多