diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java index d2894cef2d..a9a1e62bbe 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java @@ -307,11 +307,20 @@ public abstract class AbstractRemoteFileOutboundGateway extends AbstractReply Assert.notNull(remoteFileTemplate, "'remoteFileTemplate' cannot be null"); this.remoteFileTemplate = remoteFileTemplate; this.command = command; - Expression parsedExpression = new SpelExpressionParser().parseExpression(expression); - this.fileNameProcessor = new ExpressionEvaluatingMessageProcessor( - parsedExpression); + if (expression == null) { + Assert.state(Command.LS.equals(this.command) + || Command.PUT.equals(this.command) + || Command.MPUT.equals(this.command), + "Only LS, PUT and MPUT commands can rely on the working directory.\n" + + "All other commands must be supplied with the filename expression"); + this.fileNameProcessor = null; + } + else { + Expression parsedExpression = new SpelExpressionParser().parseExpression(expression); + this.fileNameProcessor = new ExpressionEvaluatingMessageProcessor(parsedExpression); + setPrimaryExpression(parsedExpression); + } this.messageSessionCallback = null; - setPrimaryExpression(parsedExpression); } /** @@ -503,10 +512,14 @@ public abstract class AbstractRemoteFileOutboundGateway extends AbstractReply "Cannot use " + Option.SUBDIRS.toString() + " when using 'mget' use " + Option.RECURSIVE.toString() + " to obtain files in subdirectories"); } - if (this.fileNameProcessor != null && getBeanFactory() != null) { - this.fileNameProcessor.setBeanFactory(this.getBeanFactory()); - this.renameProcessor.setBeanFactory(this.getBeanFactory()); - this.remoteFileTemplate.setBeanFactory(this.getBeanFactory()); + + if (getBeanFactory() != null) { + if (this.fileNameProcessor != null) { + this.fileNameProcessor.setBeanFactory(getBeanFactory()); + } + + this.renameProcessor.setBeanFactory(getBeanFactory()); + this.remoteFileTemplate.setBeanFactory(getBeanFactory()); } } @@ -542,7 +555,9 @@ public abstract class AbstractRemoteFileOutboundGateway extends AbstractReply } private Object doLs(Message requestMessage) { - String dir = this.fileNameProcessor.processMessage(requestMessage); + String dir = this.fileNameProcessor != null + ? this.fileNameProcessor.processMessage(requestMessage) + : null; if (dir != null && !dir.endsWith(this.remoteFileTemplate.getRemoteFileSeparator())) { dir += this.remoteFileTemplate.getRemoteFileSeparator(); } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java index bd4a59b769..a35192481b 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java @@ -821,7 +821,7 @@ public class RemoteFileOutboundGatewayTests { template.setRemoteDirectoryExpression(new LiteralExpression("foo/")); template.setBeanFactory(mock(BeanFactory.class)); template.afterPropertiesSet(); - TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "put", null); + TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "put", "payload"); FileTransferringMessageHandler handler = new FileTransferringMessageHandler(sessionFactory); handler.setRemoteDirectoryExpressionString("'foo/'"); handler.setBeanFactory(mock(BeanFactory.class)); @@ -856,7 +856,7 @@ public class RemoteFileOutboundGatewayTests { template.setRemoteDirectoryExpression(new LiteralExpression("foo/")); template.setBeanFactory(mock(BeanFactory.class)); template.afterPropertiesSet(); - TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "put", null); + TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "put", "payload"); FileTransferringMessageHandler handler = new FileTransferringMessageHandler(sessionFactory); handler.setRemoteDirectoryExpression(new LiteralExpression("foo/")); handler.setBeanFactory(mock(BeanFactory.class)); @@ -917,7 +917,7 @@ public class RemoteFileOutboundGatewayTests { template.setRemoteDirectoryExpression(new LiteralExpression("foo/")); template.setBeanFactory(mock(BeanFactory.class)); template.afterPropertiesSet(); - TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "mput", null); + TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "mput", "payload"); gw.afterPropertiesSet(); when(sessionFactory.getSession()).thenReturn(session); final AtomicReference written = new AtomicReference(); diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java index 7275f64b63..016b89eedf 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/gateway/FtpOutboundGateway.java @@ -86,8 +86,8 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway The {@code remoteDirectory} expression is {@code null} assuming to use * the {@code workingDirectory} from the FTP Client. * @param sessionFactory the session factory. @@ -99,8 +99,8 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway The {@code remoteDirectory} expression is {@code null} assuming to use * the {@code workingDirectory} from the FTP Client. * @param remoteFileTemplate the remote file template. diff --git a/src/reference/asciidoc/ftp.adoc b/src/reference/asciidoc/ftp.adoc index e59e42aeb5..a1275919e0 100644 --- a/src/reference/asciidoc/ftp.adoc +++ b/src/reference/asciidoc/ftp.adoc @@ -684,8 +684,9 @@ directories, which is achievable using the `FileInfo` objects. Starting with _version 4.3_, the `FtpSession` supports `null` for the `list()` and `listNames()` methods, therefore the `expression` attribute can be omitted. -From Java perspective there are two new constructor without `expression` argument for convenience. -The `null` for `LS` command is treated as an Client working directory according to the FTP protocol. +For Java configuration, there are two constructors without an `expression` argument for convenience. +`null` for `LS`, `PUT` and `MPUT` commands is treated as the Client working directory according to the FTP protocol. +All other commands must be supplied with the `expression` to evaluate remote path against request message. The working directory can be set via the `FTPClient.changeWorkingDirectory()` function when you extend the `DefaultFtpSessionFactory` and implement `postProcessClientAfterConnect()` callback. *get*