Hello Camel users, I've noticed some odd behavior with the SFTP component in combination with "move" that I was hoping I could get some clarity on - perhaps it's a misconfiguration or misunderstanding on my end. Given a route using the component as a consumer like the following:
public class DownloadAndRenameSftpRoute extends RouteBuilder { @Override public void configure() { from(String.format("sftp:%s:%s/%s?username=%s&password=%s", SFTP_IP_ADDRESS, SFTP_PORT, "test/data", SFTP_USERNAME, SFTP_PASSWORD) + "&download=true" + "&autoCreate=false" + "&greedy=true" + "&move=${file:onlyname}.old" + "&maxMessagesPerPoll=1" + "&scheduler=quartz" + "&scheduler.cron=0/2+*+*+?+*+*+*") // poll every 2 seconds .to("direct:get_file"); } } I would expect that on completion of the exchange a file (say "garbage") on the remote is successfully renamed from "garbage" to "garbage.old". If I do something like: try (CamelContext context = new DefaultCamelContext()) { context.addRoutes(new DownloadAndRenameSftpRoute()); context.start(); ConsumerTemplate consumerTemplate = context.createConsumerTemplate(); Exchange exchange = consumerTemplate.receive("direct:get_file", 5000L); consumerTemplate.doneUoW(exchange); consumerTemplate.stop(); context.stop(); } The file /is/ successfully renamed on the remote, but the engine seems to have a different view of the world, since it complains with the following (apologies for the long stack trace): 2020-08-27 22:02:39.309Z WARN org.apache.camel.component.file.GenericFileOnCompletion:212 - Error during commit. Exchange[ID-C02YV0J3LVDQ-local-1598565757117-0-3]. Caused by: [org.apache.camel.component.file.GenericFileOperationFailedException - Cannot rename file from: test/data/garbage to: test/data/garbage.old] org.apache.camel.component.file.GenericFileOperationFailedException: Cannot rename file from: test/data/garbage to: test/data/garbage.old at org.apache.camel.component.file.remote.SftpOperations.renameFile(SftpOperations.java:503) ~[camel-ftp-3.4.0.jar:3.4.0] at org.apache.camel.component.file.strategy.GenericFileProcessStrategySupport.renameFile(GenericFileProcessStrategySupport.java:136) ~[camel-file-3.4.0.jar:3.4.0] at org.apache.camel.component.file.strategy.GenericFileRenameProcessStrategy.commit(GenericFileRenameProcessStrategy.java:115) ~[camel-file-3.4.0.jar:3.4.0] at org.apache.camel.component.file.GenericFileOnCompletion.processStrategyCommit(GenericFileOnCompletion.java:132) [camel-file-3.4.0.jar:3.4.0] at org.apache.camel.component.file.GenericFileOnCompletion.onCompletion(GenericFileOnCompletion.java:85) [camel-file-3.4.0.jar:3.4.0] at org.apache.camel.component.file.GenericFileOnCompletion.onComplete(GenericFileOnCompletion.java:59) [camel-file-3.4.0.jar:3.4.0] at org.apache.camel.support.UnitOfWorkHelper.doneSynchronizations(UnitOfWorkHelper.java:91) [camel-support-3.4.0.jar:3.4.0] at org.apache.camel.impl.engine.DefaultUnitOfWork.done(DefaultUnitOfWork.java:216) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.support.UnitOfWorkHelper.doneUow(UnitOfWorkHelper.java:54) [camel-support-3.4.0.jar:3.4.0] at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:651) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.processor.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:594) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.processor.CamelInternalProcessor$AsyncAfterTask.done(CamelInternalProcessor.java:174) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.AsyncCallback.run(AsyncCallback.java:46) [camel-api-3.4.0.jar:3.4.0] at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:60) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.processor.Pipeline.process(Pipeline.java:147) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:286) [camel-base-3.4.0.jar:3.4.0] at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:483) [camel-file-3.4.0.jar:3.4.0] at org.apache.camel.component.file.remote.RemoteFileConsumer.processExchange(RemoteFileConsumer.java:146) [camel-ftp-3.4.0.jar:3.4.0] at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:234) [camel-file-3.4.0.jar:3.4.0] at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:196) [camel-file-3.4.0.jar:3.4.0] at org.apache.camel.support.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:187) [camel-support-3.4.0.jar:3.4.0] at org.apache.camel.support.ScheduledPollConsumer.run(ScheduledPollConsumer.java:106) [camel-support-3.4.0.jar:3.4.0] at org.apache.camel.pollconsumer.quartz.QuartzScheduledPollConsumerJob.execute(QuartzScheduledPollConsumerJob.java:61) [camel-quartz-3.4.0.jar:3.4.0] at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [quartz-2.3.2.jar:?] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.3.2.jar:?] Caused by: com.jcraft.jsch.SftpException: No such file at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873) ~[jsch-0.1.55.jar:?] at com.jcraft.jsch.ChannelSftp.rename(ChannelSftp.java:1950) ~[jsch-0.1.55.jar:?] at org.apache.camel.component.file.remote.SftpOperations.renameFile(SftpOperations.java:499) ~[camel-ftp-3.4.0.jar:3.4.0] ... 25 more A cursory search online suggests a few things - such as setting "stepwise" to the non-default setting - nothing doing there, since I get the same error as above. Delving into the code seems to suggest JSch and Camel have differing views on what happened, since JSch throws an exception claiming the file wasn't found (which Camel happily re-throws), but this seems odd given that the file /was/ renamed after all. I've tested this against an Alpine Linux VM as the remote as well as another "real" system and I get the same error. Any pointers as to what's going on are much appreciated! Best, Anthony