Spring 集成 - 使用 DSL 的 FtpInboundFileSynchronizer 比较器配置

Spring Integration - FtpInboundFileSynchronizer Comparator configuration with DSL

Spring 集成的 FtpInboundFileSynchronizer 允许设置 Comparator<FTPFile> 以允许对下载进行排序。文档说:

Starting with version 5.1, the synchronizer can be provided with a Comparator. This is useful when restricting the number of files fetched with maxFetchSize.

这对@Bean 配置没问题:

 @Bean
 public FtpInboundFileSynchronizer ftpInboundFileSynchronizer(...)
        FtpInboundFileSynchronizer synchronizer = new FtpInboundFileSynchronizer(sessionFactory);
        ...
        synchronizer.setComparator(comparator);
        return synchronizer;
    }

但如果我想以编程方式 assemble 流,则鼓励使用 Java DSL。

 StandardIntegrationFlow flow = IntegrationFlows
                .from(Ftp.inboundAdapter(ftpFileSessionFactory, comparator)
                                .maxFetchSize(1)
    ...

Ftp.inboundAdapter(...)工厂方法中的比较器仅用于文件下载后本地比较。这里有一些配置设置传递给同步器(如远程目录、时间戳等)。但是同步器没有设置等同于上面的设置。

解决方案尝试:

另一种方法是将同步器创建为非 bean,以类似的方式创建 FtpInboundFileSynchronizingMessageSource,然后使用 IntegrationFlows.from(source) 到 assemble 同步器会导致运行时异常流已注册到流上下文:

Creating EvaluationContext with no beanFactory
java.lang.RuntimeException: No beanFactory
    at org.springframework.integration.expression.ExpressionUtils.createStandardEvaluationContext(ExpressionUtils.java:90) ~[spring-integration-core-5.3.2.RELEASE.jar:5.3.2.RELEASE]
    at org.springframework.integration.file.remote.synchronizer.AbstractInboundFileSynchronizer.afterPropertiesSet(AbstractInboundFileSynchronizer.java:299) ~[spring-integration-file-5.3.2.RELEASE.jar:5.3.2.RELEASE]

有道理; FtpInboundFileSynchronizer 不应在上下文之外构建。 (尽管这似乎确实有效。)但是,在那种情况下,我如何动态地 assemble ftp 集成流与配置有 Comparator<FTPFile> 的同步器?

看起来我们错过了在 DSL 中公开 remoteComparator 选项。

随时提出 GH 问题甚至贡献修复:https://github.com/spring-projects/spring-integration/issues

作为动态流的解决方法,我真的建议使用单独的 FtpInboundFileSynchronizerFtpInboundFileSynchronizingMessageSource,然后使用提到的 IntegrationFlows.from(source)。您可能在配置中遗漏的是 API:

    /**
     * Add an object which will be registered as an {@link IntegrationFlow} dependant bean in the
     * application context. Usually it is some support component, which needs an application context.
     * For example dynamically created connection factories or header mappers for AMQP, JMS, TCP etc.
     * @param bean an additional arbitrary bean to register into the application context.
     * @return the current builder instance
     */
    IntegrationFlowRegistrationBuilder addBean(Object bean);

我的意思是 FtpInboundFileSynchronizingMessageSource 可以按原样传递给 from(),但是必须添加 synchronizer 作为注册的额外 bean。

另一种更奇特的方法是考虑使用称为 DSL 扩展的新功能:https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/dsl.html#java-dsl-extensions

因此,您可以扩展 FtpInboundChannelAdapterSpec 以提供错过的选项来配置内部 synchronizer