【问题标题】:Error: EL1004E: Method call: Method rename(java.lang.String,java.lang.String) cannot be found on type com.jcraft.jsch.ChannelSftp$2错误:EL1004E:方法调用:在类型 com.jcraft.jsch.ChannelSftp$2 上找不到方法重命名(java.lang.String,java.lang.String)
【发布时间】: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 中的有效负载。事务正在运行,但表达式评估在 afterCommitafterRollBack 操作中失败,并且文件没有被重命名。 我从该方法 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


    【解决方案1】:

    您的问题在这里: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')"));
    

    【讨论】:

    • 非常感谢,就是这样。我只对重命名远程文件感兴趣。
    猜你喜欢
    • 1970-01-01
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多