FileInputStreamCache верблюда закрывается перед отправкой данных обратно клиенту REST через компоновку CXFRS
Я использую компонент camel-cxfrs для сопоставления простой операции REST GET, которая возвращает данные, извлеченные из внешнего ресурса. Все работало нормально, пока я не решил включить "streamCache", потому что возвращаемые данные иногда могут быть очень большими (до 50 МБ), и мы не хотим загружать их в память, иначе нам не хватило бы памяти при выполнении нескольких запросов одновременно! Поэтому я настроил DefaultStreamCachingStrategy, чтобы определить, когда следует передавать данные в файл tmp (например, для данных размером более 1 МБ).
Это работает нормально, как только мои данные извлекаются из внешних ресурсов (большой двоичный объект в БД!!), они передаются обратно вызывающей стороне, и поскольку данные превышают пороговое значение, Camel преобразует мой входной поток в FileInputStreamCache, что нормально... пока ответ не будет готов к возвращению вызывающей стороне через компонент CXF! Поскольку сообщение передается компоненту CXF, обмен Camel больше не требуется (выходное сообщение выходит из контекста Camel), поэтому созданный файл tmp удаляется Camel (как реализовано его TempFileManager) до того, как содержимое полностью возвращается в REST. клиент!!
Это вызывает исключение IOException, поскольку компонент CXF пытается прочитать данные из входного потока (который был только что закрыт Camel) в клиент http.
Есть идеи, как решить эту проблему?? Мне нужно держать файл tmp открытым, пока все данные ответов не будут отправлены обратно в REST Client. Но это должен быть закрыт и удален после отправки ответа.
Вот как определяется мой контекст 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;
}
}