Spring Integration - configuração do comparador FtpInboundFileSynchronizer com DSL

Aug 22 2020

O Spring Integration FtpInboundFileSynchronizerpermite a configuração de um Comparator<FTPFile>para permitir a ordenação dos downloads. A documentação diz:

A partir da versão 5.1, o sincronizador pode ser fornecido com um Comparator. Isso é útil ao restringir o número de arquivos buscados com maxFetchSize.

Isso é bom para a configuração do @Bean:

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

Mas se eu quiser montar fluxos programaticamente, o Java DSL é recomendado.

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

O comparador no Ftp.inboundAdapter(...)método de fábrica serve apenas para comparação de arquivos localmente, após o download. Existem definições de configuração que são passadas para o sincronizador aqui (como diretório remoto, timestamp, etc.). Mas não há nenhuma configuração para o sincronizador equivalente à configuração acima.

Tentativa de solução:

A alternativa é criar o sincronizador como não-bean, criar o FtpInboundFileSynchronizingMessageSourcede forma semelhante e usar IntegrationFlows.from(source)para montar o sincronizador resulta em uma exceção de tempo de execução quando o fluxo é registrado com o contexto do fluxo:

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]

Isso faz sentido; o FtpInboundFileSynchronizernão deve ser construído fora de um contexto. (Embora isso pareça funcionar.) Mas como, nesse caso, posso montar dinamicamente os fluxos de integração ftp com um sincronizador configurado com um Comparator<FTPFile>?

Respostas

2 ArtemBilan Aug 24 2020 at 20:47

Parece que esquecemos de expor essa remoteComparatoropção no DSL.

Sinta-se à vontade para levantar um problema de GH ou até mesmo contribuir com uma correção:https://github.com/spring-projects/spring-integration/issues

Como uma solução alternativa para fluxos dinâmicos, eu realmente sugeriria ir separadamente FtpInboundFileSynchronizere FtpInboundFileSynchronizingMessageSourceusar o arquivo IntegrationFlows.from(source). O que você provavelmente sente falta em sua configuração é esta 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);

Quero dizer que não FtpInboundFileSynchronizingMessageSourcehá problema em passar para o from()como está, mas synchronizerdeve ser adicionado como um bean extra para registro.

Outra maneira mais sofisticada é considerar o uso de um novo recurso chamado extensões DSL:https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/dsl.html#java-dsl-extensions

Portanto, você pode estender isso FtpInboundChannelAdapterSpecpara fornecer uma opção perdida para configurar um arquivo synchronizer.