我正在尝试在事务结束时使用Spring Boot Integration重命名远程sftp服务器中的文件。在官方文档中,他们提供了使用TransactionSynchronizationFactory和类似于的SpEL表达式的示例
@Bean
public TransactionSynchronizationFactory transactionSynchronizationFactory(){
ExpressionEvaluatingTransactionSynchronizationProcessor processor = new ExpressionEvaluatingTransactionSynchronizationProcessor();
SpelExpressionParser spelParser = new SpelExpressionParser();
processor.setAfterCommitExpression(spelParser.parseRaw(
"payload.renameTo(headers['file_remoteDirectory']+'/'+headers['file_remoteFile'] ,headers['file_remoteDirectory']+'/'+headers['file_remoteFile']+'.PASSED')"));
processor.setAfterRollbackExpression(spelParser.parseRaw(
"payload.renameTo(headers['file_remoteDirectory']+'/'+headers['file_remoteFile'] ,headers['file_remoteDirectory']+'/'+headers['file_remoteFile']+'.FAILED')"));
return new DefaultTransactionSynchronizationFactory(processor);
}
在我的实现中,我不使用File对象,而是使用InputStream作为sftpAdapter中的有效负载。事务正在运行,但在afterCommit和posterCollBack操作中表达式求值失败,并且未重命名文件。我在该方法中出现以下错误:
EL1004E:方法调用:在类型com.jcraft.jsch.ChannelSftp$2 上找不到方法重命名(java.lang.String,java.lang.Sstring(
这是我的实现:
@Bean
@InboundChannelAdapter(channel = sftp-inChannel",
poller = @Poller(value = "pollerMetadata"),
autoStartup = "${sftp.autoStartup:true}")
public MessageSource<InputStream> ftpMessageSource() {
SftpStreamingMessageSource source = new SftpStreamingMessageSource(sftpRemoteFileTemplate());
source.setRemoteDirectory(path);
source.setFilter(chainFilter());
source.setMaxFetchSize(maxFetchSize);
return source;
}
@Bean
public PollerMetadata pollerMetadata() {
return Pollers.fixedRate(delayInMillisec)
.maxMessagesPerPoll(maxFetchSize)
.advice(transactionInterceptor())
.transactionSynchronizationFactory(transactionSynchronizationFactory())
.transactional()
.get();
}
@Bean
public TransactionSynchronizationFactory transactionSynchronizationFactory(){
ExpressionEvaluatingTransactionSynchronizationProcessor processor = new ExpressionEvaluatingTransactionSynchronizationProcessor();
SpelExpressionParser spelParser = new SpelExpressionParser();
processor.setAfterCommitExpression(spelParser.parseRaw(
"payload.rename(headers['file_remoteDirectory']+'/'+headers['file_remoteFile'] ,headers['file_remoteDirectory']+'/'+headers['file_remoteFile']+'.PASSED')"));
processor.setAfterRollbackExpression(spelParser.parseRaw(
"payload.rename(headers['file_remoteDirectory']+'/'+headers['file_remoteFile'] ,headers['file_remoteDirectory']+'/'+headers['file_remoteFile']+'.FAILED')"));
return new DefaultTransactionSynchronizationFactory(processor);
}
我可以看到类ChannelSftp有一个.rename(String,String(方法,并且是有效负载的类型,但SpEL似乎无法看到从GenericMessage到ChannelSftp的转换,因此无法看到.rename(String,String(方法。我花了一天时间试图在文档中找到一些东西,但没有成功,任何帮助都将不胜感激。
感谢
您的问题在这里:com.jcraft.jsch.ChannelSftp$2
。注意$2
。这已经不是ChannelSftp
,而是远程文件的内部InputStream
。这正是SftpStreamingMessageSource
正在产生的。它不返回文件,也不返回ChannelSftp
。您不能在InputStream
上调用rename()
。
请考虑使用特殊的IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE
标头。这是org.springframework.integration.file.remote.session.Session
的一个实例,它已经具有所需的rename(String pathFrom, String pathTo)
方法。但是再一次:这个将为远程文件做这件事:
processor.setAfterCommitExpression(spelParser.parseRaw(
"headers.closeableResource.rename(headers['file_remoteDirectory']+'/'+headers['file_remoteFile'] ,headers['file_remoteDirectory']+'/'+headers['file_remoteFile']+'.PASSED')"));