Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for MV command to use remote directory + remote file name => new file name (in the same remote directory) #3647

Closed
mauromol opened this issue Oct 19, 2021 · 3 comments · Fixed by #3651

Comments

@mauromol
Copy link
Contributor

mauromol commented Oct 19, 2021

Expected Behavior

I would like to do something like this (I'm using SFTP, but I think this is common to other remote file gateways):

<int-sftp:outbound-gateway
  session-factory="mySftpSessionFactory"
  request-channel="myRequestChannel" 
  reply-channel="nullChannel"
  command="mv"
  remote-directory-expression="headers[T(org.springframework.integration.file.FileHeaders).REMOTE_DIRECTORY]"
  expression="headers[T(org.springframework.integration.file.FileHeaders).REMOTE_FILE]"
  rename-expression="headers[T(org.springframework.integration.file.FileHeaders).REMOTE_FILE].concat('.done')"  />

That is: consider the file located under remote-directory-expression, with simple name given by expression, and rename it to rename-expression, which is a simple name (not a full path), hence keeping the renamed file in in the same source directory.

i.e.: for file "example.txt" in /sourcepath to be renamed to "example.txt.done" they would be:

  • remote-directory-expression = /sourcepath
  • expression = example.txt
  • rename-expression = example.txt.done

Current Behavior
expression must be a full path, as well as rename-expression, while remote-directory-expression seems to be simply ignored. This causes the above to lead to a "file does not exist" error.

In org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.doMv(Message<?>) (I'm using Spring Integration 5.4.11) I see this:

String remoteFilePath = obtainRemoteFilePath(requestMessage);
String remoteFilename = getRemoteFilename(remoteFilePath);
String remoteDir = getRemoteDirectory(remoteFilePath, remoteFilename);
String remoteFileNewPath = this.renameProcessor.processMessage(requestMessage);

By debugging I see that:

  • remoteFilePath is example.txt
  • remoteFilename is example.txt as well
  • remoteDir is null, because it tries to extract the path by removing the remoteFileName from remoteFilePath (ignoring my remote-directory-expression)
  • remoteFileNewPath is example.txt.done

Perhaps, if that code used remote-directory-expression in case remoteDir is null, and possibly concatenate that remoteDir with remoteFileNewPath in case the latter is not a full path, could bring the desired result without breaking backward compatibility.

Context
I'm trying to rename a file I have previously read with a <int-sftp:inbound-streaming-channel-adapter> on transaction commit. The inbound adapter only allows for file deletion after read, not file rename/move, and I'm not sure whether the action is executed immediately after reading the source file or at the end of the flow if no exception is got back by downstream components (as I want in my case).
Anyway, in my case I would like to just add a suffix to the file name, without moving it anywhere, so I'd like to limit processing as much as possible, in particular to avoid to make concatenations just to reference a file for which I already know both the remote directory and its simple file name.

Unless I'm missing a better way to do this, the alternative way to achieve this right now is to write the following (which seems a bit ugly to me):

<int-sftp:outbound-gateway
  session-factory="mySftpSessionFactory"
  request-channel="myRequestChannel" 
  reply-channel="nullChannel"
  command="mv"
  expression="headers[T(org.springframework.integration.file.FileHeaders).REMOTE_DIRECTORY].concat('/'.concat(headers[T(org.springframework.integration.file.FileHeaders).REMOTE_FILE]))"
  rename-expression="headers[T(org.springframework.integration.file.FileHeaders).REMOTE_DIRECTORY].concat('/'.concat(headers[T(org.springframework.integration.file.FileHeaders).REMOTE_FILE].concat('.done')))"  />
@mauromol mauromol added status: waiting-for-triage The issue need to be evaluated and its future decided type: enhancement labels Oct 19, 2021
@artembilan artembilan self-assigned this Oct 20, 2021
@artembilan artembilan added this to the 5.5.x milestone Oct 20, 2021
@artembilan artembilan added in: ftp in: sftp and removed status: waiting-for-triage The issue need to be evaluated and its future decided labels Oct 20, 2021
@artembilan artembilan modified the milestones: 5.5.x, 5.5.6 Oct 20, 2021
@artembilan
Copy link
Member

Confirmed.

Will take care about such an improvement shortly.

Thank you!

artembilan added a commit that referenced this issue Oct 20, 2021
Fixes #3647

To simplify a source and renameTo remote file expressions, the `remoteDirectoryExpression`
is consulted now, when they are not full paths.
This is useful when we want just to rename a remote file in some dir
@mauromol
Copy link
Contributor Author

I must say that the documentation for the SFTP outbound gateway is a bit confusing to describe which attribute does what with the different commands, at least this is my humble feeling. Today I had to go by trial and error and debug to make a recursive mget work as desired. I may open a new documentation issue for that, anyway from what I read I suspect that an enhancement similar to this one could be made for the rm command as well (remote directory + simple file name instead of full path to the file to delete).

@artembilan
Copy link
Member

Yes, please, raise a separate issue for docs.

Re. rm. I don't feel like we are going to gain something from two expressions configuration instead of one. Since both of them can be combined in a single one anyway, even if both dir and file are dynamic in our flow logic.
But still: since you expressed your concern, I won't mind to make that change, too.

Let's see if @garyrussell is OK with adding this to an open PR or better to address it separately.

Thanks

garyrussell pushed a commit that referenced this issue Oct 21, 2021
* GH-3647: Use remoteDirExpression in MV command

Fixes #3647

To simplify a source and renameTo remote file expressions, the `remoteDirectoryExpression`
is consulted now, when they are not full paths.
This is useful when we want just to rename a remote file in some dir

* * Add JavaDoc for `getDirectoryExpressionProcessor()`
* Fix language in docs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants