【发布时间】:2021-12-30 21:26:34
【问题描述】:
我正在尝试在事务结束时重命名远程 sftp 服务器中的文件并使用 Spring Boot 集成。在官方documentation 中,他们提供了使用 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 和 afterRollBack 操作中失败,并且文件没有被重命名。 我从该方法 org.springframework.expression.spel.standard.SpelExpression#getValue(org.springframework.expression.EvaluationContext, java.lang.Object) 遇到以下错误:
EL1004E: 方法调用:在类型 com.jcraft.jsch.ChannelSftp$2 上找不到方法 rename(java.lang.String,java.lang.String)
这是我的实现:
@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) 方法。 我花了一天时间试图在文档中找到一些没有成功的东西,任何帮助将不胜感激。
谢谢
【问题讨论】:
标签: spring spring-boot spring-integration spring-transactions spring-el