I am using camel-cxfrs component to map a simple REST GET operation that returns data extracted from an external resource. Everything was working fine until I decided to enable "streamCache" because the data to return can sometime be very large (up to 50MB) and we do not want to load it in memory, otherwise we would ran out of memory when multiple requests are performed simultaneously! So I configured a DefaultStreamCachingStrategy to define when to stream data to a tmp file (on data larger than 1MB for example).
This is working fine, once my data is fetched from external resources (blob in DB!!), it is streamed out back to the caller, and because the data is larger than the threshold value, Camel is converting my inputstream into a FileInputStreamCache, which is fine... until the response is ready to be returned to the caller through the CXF component! Because the message is passed to CXF component, the Camel exchange is no longer required (the output message left Camel context), so the created tmp file is deleted by Camel (as implemented by its TempFileManager) before the content was fully returned to the REST client!!
This is causing an IOException since the CXF component is trying to read the data from the inputstream ( which has just been closed by Camel) to the http client.
Any idea how to solve this problem?? I would need to keep the tmp file opened until all the response data can be be sent back to REST Client. But is has to be closed and deleted once response sent.
Here how my Camel context and some beans defined (not showing everything):
<!-- ... -->
<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>
And next, the endpoint class used to map REST request:
@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;
}
}