Фон системы: Windows/ServiceMix/Camel/Smooks
У меня есть маршрут Camel
<camel:camelContext id="customsContext" xmlns="http://camel.apache.org/schema/spring">
<camel:route>
<camel:from uri="file://C:\Camel\?delay=2000"/>
<camel:convertBodyTo type="javax.xml.transform.stream.StreamSource"/>
<camel:to uri="smooks:smooks-config.xml"/>
</camel:route>
</camel:camelContext>
который должен забрать файл и передать его пользовательскому анализатору EDI Smooks. Это работает до того момента, когда Camel копирует файл в каталог moveNamePrefix
, а затем пытается удалить оригинал, когда выдает исключение. Поскольку файл никогда не очищается, это повторяется бесконечно.
2014-06-04 23:43:47,331 | WARN | ://C:%5CCamel%5C | GenericFileOnCompletion | ? ? | 110 - org.apache.camel.camel-core - 2.12.3 | Error during commit. Exchange[Message: [Body is null]]. Caused by: [org.apache.camel.component.file.GenericFileOperationFailedException - Error renaming file from C:\Camel\edi-input.txt to C:\Camel\.camel\edi-input.txt]
org.apache.camel.component.file.GenericFileOperationFailedException: Error renaming file from C:\Camel\edi-input.txt to C:\Camel\.camel\edi-input.txt
at org.apache.camel.component.file.FileOperations.renameFile(FileOperations.java:72)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.strategy.GenericFileProcessStrategySupport.renameFile(GenericFileProcessStrategySupport.java:113)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.strategy.GenericFileRenameProcessStrategy.commit(GenericFileRenameProcessStrategy.java:88)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.GenericFileOnCompletion.processStrategyCommit(GenericFileOnCompletion.java:124)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.GenericFileOnCompletion.onCompletion(GenericFileOnCompletion.java:80)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.GenericFileOnCompletion.onComplete(GenericFileOnCompletion.java:54)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.util.UnitOfWorkHelper.doneSynchronizations(UnitOfWorkHelper.java:100)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.impl.DefaultUnitOfWork.done(DefaultUnitOfWork.java:228)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.util.UnitOfWorkHelper.doneUow(UnitOfWorkHelper.java:61)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:613)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:581)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.processor.CamelInternalProcessor$InternalCallback.done(CamelInternalProcessor.java:240)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:106)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:401)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:201)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:165)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:187)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:114)[110:org.apache.camel.camel-core:2.12.3]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)[:1.7.0_51]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)[:1.7.0_51]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)[:1.7.0_51]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)[:1.7.0_51]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)[:1.7.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)[:1.7.0_51]
at java.lang.Thread.run(Thread.java:744)[:1.7.0_51]
Caused by: java.io.IOException: Renaming file from: C:\Camel\edi-input.txt to: C:\Camel\.camel\edi-input.txt failed due cannot delete from file: C:\Camel\edi-input.txt after copy succeeded
at org.apache.camel.util.FileUtil.renameFile(FileUtil.java:421)[110:org.apache.camel.camel-core:2.12.3]
at org.apache.camel.component.file.FileOperations.renameFile(FileOperations.java:70)[110:org.apache.camel.camel-core:2.12.3]
... 25 more
Так что да, файл все еще открыт, что блокирует удаление. Но тут становится немного интересно. Если вы перечисляете открытые файлы, вы видите, что они на самом деле открыты несколько раз, и вы получаете еще один каждые 2 секунды, что является задержкой опроса.
#1 C:\Camel\edi-input.txt by thread:Camel (customsContext) thread #0 - file://C:%5CCamel%5C on Thu Jun 05 10:08:13 EDT 2014
at java.io.FileInputStream.<init>(FileInputStream.java:147)
at java.io.FileInputStream.<init>(FileInputStream.java:101)
at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
at java.net.URL.openStream(URL.java:1037)
at org.milyn.delivery.AbstractParser.systemIdToStream(AbstractParser.java:192)
at org.milyn.delivery.AbstractParser.getInputStream(AbstractParser.java:253)
at org.milyn.delivery.AbstractParser.createInputSource(AbstractParser.java:227)
at org.milyn.delivery.sax.SAXParser.parse(SAXParser.java:76)
at org.milyn.delivery.sax.SmooksSAXFilter.doFilter(SmooksSAXFilter.java:86)
at org.milyn.delivery.sax.SmooksSAXFilter.doFilter(SmooksSAXFilter.java:64)
at org.milyn.Smooks._filter(Smooks.java:526)
at org.milyn.Smooks.filterSource(Smooks.java:477)
at org.milyn.smooks.camel.processor.SmooksProcessor.process(SmooksProcessor.java:112)
at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:103)
at org.apache.camel.impl.ProcessorEndpoint$1.process(ProcessorEndpoint.java:71)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:110)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:72)
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:398)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:118)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)
at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:401)
at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:201)
at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:165)
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:187)
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:114)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Тем не менее, их меньше 100, хотя на данный момент завершено ~ 7000 циклов, так что да, все файлы закрываются во время GC (сборки мусора), а затем снова начинают накапливаться. Да, это говорит о том, что поток не закрывается до тех пор, пока ссылающийся на него объект не будет очищен сборщиком мусора. Однако я отследил код, и поток закрыт в org.milyn.delivery.sax.SmooksSAXFilter.doFilter
try {
Writer writer = parser.parse(source, result, executionContext);
writer.flush();
} catch (TerminateException e) {
if(logger.isDebugEnabled()) {
if(e.isTerminateBefore()) {
logger.debug("Terminated filtering on visitBefore of element '" + SAXUtil.getXPath(e.getElement()) + "'.");
} else {
logger.debug("Terminated filtering on visitAfter of element '" + SAXUtil.getXPath(e.getElement()) + "'.");
}
}
} catch (Exception e) {
throw new SmooksException("Failed to filter source.", e);
} finally {
if(closeSource) {
close(source);
}
if(closeResult) {
close(result);
}
}
Так что тут я немного в растерянности. Означает ли это, что Camel пытается зафиксировать транзакцию в другом потоке до того, как Smooks завершит работу?