在通过CXFRS组件将数据发送回REST客户端之前,Camel的FileInputStreamCache已关闭

时间:2017-06-02 19:37:12

标签: apache-camel cxfrs camel-cxf

我使用camel-cxfrs组件来映射一个简单的REST GET操作,该操作返回从外部资源中提取的数据。一切都很好,直到我决定启用" streamCache"因为要返回的数据有时会非常大(最多50MB),我们不想将其加载到内存中,否则我们会在同时执行多个请求时耗尽内存! 所以我配置了一个DefaultStreamCachingStrategy来定义何时将数据流传输到tmp文件(例如,大于1MB的数据)。

这工作正常,一旦我的数据从外部资源(数据库中的blob !!)获取,它就会流回到调用者,并且因为数据大于阈值,Camel正在将我的输入流转换为一个FileInputStreamCache,这很好......直到响应准备好通过CXF组件返回给调用者!因为消息传递给CXF组件,所以不再需要Camel交换(输出消息留下Camel上下文),因此在内容完全返回到REST之前,Camel删除创建的tmp文件(由其TempFileManager实现)客户端!
这导致IOException,因为CXF组件正在尝试从输入流(刚刚被Camel关闭)读取数据到http客户端。

任何想法如何解决这个问题?我需要保持tmp文件打开,直到所有响应数据都可以发送回REST客户端。但是一旦发送响应,就必须关闭并删除。

这里我的Camel上下文和一些bean是如何定义的(不显示所有内容):

<!-- ... -->
<cxf:rsServer address="/path" id="rsServer">
    <cxf:providers>
        <!-- ... -->
    </cxf:providers>
    <cxf:serviceBeans>
        <ref bean="resourcesEndpoint"/>
    </cxf:serviceBeans>
    <!-- ... -->
</cxf:rsServer>
<!-- ... -->

<bean class="org.apache.camel.impl.DefaultStreamCachingStrategy" id="streamStrategy">
    <property name="enabled" value="true"/>
    <property name="bufferSize" value="512000"/>
    <property name="spoolThreshold" value="512000"/>
    <property name="spoolUsedHeapMemoryThreshold" value="8}"/>
    <property name="spoolUsedHeapMemoryLimit" value="Max"/>
    <property name="removeSpoolDirectoryWhenStopping" value="true"/>
    <property name="anySpoolRules" value="true"/>
</bean>
<!-- ... -->

<camelContext id="context" streamCache="true" trace="false" useBreadcrumb="true" useMDCLogging="true" xmlns="http://camel.apache.org/schema/spring">
    <!-- ... -->
    <route id="mainRoute" >
        <from id="fromCXFEndpoint" uri="cxfrs:bean:rsServer?bindingStyle=SimpleConsumer"/>
        <recipientList id="_recipientList1">
            <simple>direct:${header.operationName}</simple>
        </recipientList>
    </route>
    <route id="downloadDataRoute" >
        <from id="fromDownloadDataCXF" uri="direct:downloadData"/>
        <!-- ... -->
        <!-- Performing data fetching... not showing everything here! -->
        <!-- ... -->
    </route>
</camelContext>

接下来,用于映射REST请求的端点类:

@Path("/resources")
@Component
@Service
public class ResourcesEndpoint {

    @GET
    @Path("/data/{guid}")
    @Produces({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM})
    public StreamingOutput downloadData(@PathParam("guid") String guid) {
        return null;
    }
}

0 个答案:

没有答案