Skip to content

"Failed to delete" warning reported for each non-replaced file by SftpOutboundGateway #3652

@mauromol

Description

@mauromol

Using Spring Integration 5.4.11

Describe the bug

When you setup a SftpOutboundGateway with a FileExistsMode set to REPLACE you'll get a series of warnings in the logs even if no replace is performed (because the local file does not exist).

To Reproduce

Create a SFTP outbound gateway like this and suppose you have the remote directory path in the message payload in the request channel:

<int-sftp:outbound-gateway
  session-factory="mySftpSessionFactory"
  request-channel="requestChannel"
  reply-channel="replyChannel"
  command="mget"
  command-options="-P -R"
  expression="payload.concat('/*')"
  local-directory-expression="'file:${java.io.tmpdir}/myappdir/'.concat(#remoteDirectory)"
  filter="myfilter"
  mode="REPLACE" />

<bean
  id="myFilter"
  class="org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter">
    <constructor-arg value="*.txt" />
    <property name="alwaysAcceptDirectories" value="true" />
</bean>

If a remote file does not exist locally, a warning gets printed in the logs:

Failed to delete /tmp/myappdir/remote/path/myFile.txt

Expected behavior

If the remote file does not currently exist locally, it does not need to be replaced, so it should not be deleted at all.

I think the problem lies in org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.get(Message<?>, Session<F>, String, String, String, F):

FileExistsMode existsMode = this.fileExistsMode;
boolean appending = FileExistsMode.APPEND.equals(existsMode);
boolean exists = localFile.exists();
boolean replacing = FileExistsMode.REPLACE.equals(existsMode)
		|| (exists && FileExistsMode.REPLACE_IF_MODIFIED.equals(existsMode)
		&& localFile.lastModified() != getModified(fileInfo));
if (!exists || appending || replacing) {
  // ...
  if (replacing && !localFile.delete()) {
    this.logger.warn(() -> "Failed to delete " + localFile);
  }
// ...

I believe that the replacing boolean value should be turned to something like this:

boolean replacing = exists && (FileExistsMode.REPLACE.equals(existsMode)
		|| (FileExistsMode.REPLACE_IF_MODIFIED.equals(existsMode)
		&& localFile.lastModified() != getModified(fileInfo)));

That is: we don't need to replace if the local file does not exist... The localFile.delete() call will always fail if the local file does not exist.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions