当前位置: 首页 > 知识库问答 >
问题:

Apache camel servlet流在split()后关闭

阮轶
2023-03-14

我需要发布一个JSON Camel Servlet,然后复制消息并拆分列表。处理每个拆分的消息,最后聚合并返回servlet响应。

然而,只要在路由中引入拆分器,我就会看到输入流正在关闭,Servlet无法写回响应。

请注意,流缓存也已启用。

from("servlet:sample")
                .log(LoggingLevel.INFO, "Message Received: JSON RQ")
                .to("direct:samplejson");
from("direct:samplejson")
    .streamCaching()
    .setHeader("sampleId", simple("${id}"))
    .log(LoggingLevel.INFO, SampleID in Header: ${header.sampleId}")
    .unmarshal().json(JsonLibrary.Jackson, Sample.class)
    .log(LoggingLevel.INFO, "Converted to JSON: ${body.toString}")
    .process("sampleProcessor")
    .split().body().streaming()
        .choice()
        .when().method("sampleProcessor", "isTypeA")
            .marshal().jacksonxml(Sample.class)
        .endChoice()
        .otherwise()
            .marshal().jacksonxml(Sample.class)
    .end()
    .aggregate(SampleAggregationStrategy).header("sampleId").completionSize(2).completionTimeout(1000L)
    .to("direct:samplexml");
from("direct:samplexml").marshal().jacksonxml(List.class).log("FINISHED PROCESSING");

例外:

2017-06-12 12:22:25,311 [apr-8080-exec-2] INFO  route1                         - FINISHED PROCESSING
2017-06-12 12:22:25,321 [apr-8080-exec-2] ERROR CamelHttpTransportServlet      - Error processing request
java.io.IOException: Stream closed
        at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:372) ~[catalina.jar:8.0.30]
        at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:156) ~[catalina.jar:8.0.30]
        at org.apache.camel.util.IOHelper.copy(IOHelper.java:196) ~[camel-core-2.19.0.jar:2.19.0]
        at org.apache.camel.http.common.DefaultHttpBinding.copyStream(DefaultHttpBinding.java:432) ~[camel-http-common-2.19.0.jar:2.19.0]
        at org.apache.camel.http.common.DefaultHttpBinding.doWriteDirectResponse(DefaultHttpBinding.java:496) ~[camel-http-common-2.19.0.jar:2.19.0]
        at org.apache.camel.http.common.DefaultHttpBinding.doWriteResponse(DefaultHttpBinding.java:395) ~[camel-http-common-2.19.0.jar:2.19.0]
        at org.apache.camel.http.common.DefaultHttpBinding.writeResponse(DefaultHttpBinding.java:322) ~[camel-http-common-2.19.0.jar:2.19.0]
        at org.apache.camel.http.common.CamelServlet.doService(CamelServlet.java:210) [camel-http-common-2.19.0.jar:2.19.0]
        at org.apache.camel.http.common.CamelServlet.service(CamelServlet.java:74) [camel-http-common-2.19.0.jar:2.19.0]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [servlet-api.jar:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [catalina.jar:8.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.30]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.30]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.30]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [catalina.jar:8.0.30]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.30]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.30]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [catalina.jar:8.0.30]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.30]
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [catalina.jar:8.0.30]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.30]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521) [catalina.jar:8.0.30]
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096) [tomcat-coyote.jar:8.0.30]
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674) [tomcat-coyote.jar:8.0.30]
        at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500) [tomcat-coyote.jar:8.0.30]
        at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489) [tomcat-coyote.jar:8.0.30]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_74]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_74]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.30]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_74]

如果我删除拆分器和聚合器,我会看到Servlet响应回来。

非常感谢您提供的所有帮助!。

共有1个答案

满昊然
2023-03-14

请参阅堆肥消息处理器EIP模式(http://camel.apache.org/composed-message-processor.html)和仅使用拆分器的示例,它允许您在同一工作单元中进行分叉/连接,并能够在servlet中返回响应。拆分器仅支持AggregationStrategy您可以配置聚合响应的位置。换句话说,不要同时使用拆分器和聚合器,而只使用拆分器。

 类似资料:
  • 我有一些代码,正在尝试从一个可能或可能没有加密的文件读取。如果它是加密的,那么它在实际数据之前有一个包含几个字节信息的头。访问该文件的逻辑如下所示: 我的问题是: 我的假设是否正确,即关闭文件然后立即打开文件的代码可能会收到此错误,因为Windows仍在释放它,即使.NET Stream.Close方法调用已返回(或using块已退出)? 有没有比延长重试间隔更不垃圾的方法呢?

  • 问题内容: 我只想知道,我们通常会在最后关闭流,但是为什么不通过以下方式关闭PrintStream 呢? 问题答案: 如果将其关闭,则将无法再写入控制台,因此,当进程终止时,让我们将此任务留给VM。您应该只关闭自己拥有或手动创建的流。不在您的控制范围之内,因此请留给创作者照顾。

  • split 方法 将字符串分割成字符串数组。 语法: stringObject.split( separator, howmany ); 参数说明: separator - 必需。字符串或正则表达式,从该参数指定的地方分割 stringObject。 howmany - 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字

  • 描述 (Description) 此函数根据PATTERN指定的分隔符将字符串表达式拆分为字段。 如果未指定模式,则空格是默认值。 可选限制限制返回的元素数。 负限制具有与无限制相同的效果。 此函数通常与join()一起使用以创建小型文本数据库。 语法 (Syntax) 以下是此函数的简单语法 - split /PATTERN/, EXPR, LIMIT split /PATTERN/, EXPR

  • Split Function返回一个数组,该数组包含基于分隔符拆分的特定数量的值。 语法 (Syntax) Split(expression[,delimiter[,count[,compare]]]) 参数描述 (Parameter Description) Expression - 必需参数。 字符串表达式,可以包含带分隔符的字符串。 Delimiter - 可选参数。 该参数,用于根据分

  • 此方法通过将字符串分隔为子字符串将String对象拆分为字符串数组。 语法 (Syntax) string.split([separator][, limit]); 参数细节 (Argument Details) separator - 指定用于分隔字符串的字符。 如果省略ifseparator,则返回的数组包含一个由整个字符串组成的元素。 limit - 整数,指定要查找的拆分数限制。 返回