Spring Integration - Configurazione del comparatore FtpInboundFileSynchronizer con DSL

Aug 22 2020

Spring Integration FtpInboundFileSynchronizerconsente l'impostazione di a Comparator<FTPFile>per consentire l'ordinamento dei download. La documentazione dice:

A partire dalla versione 5.1, il sincronizzatore può essere dotato di un comparatore. Questo è utile quando si limita il numero di file recuperati con maxFetchSize.

Questo va bene per la configurazione @Bean:

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

Ma se voglio assemblare in modo programmatico i flussi, il Java DSL è incoraggiato.

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

Il comparatore nel Ftp.inboundAdapter(...)metodo di fabbrica è solo per il confronto dei file in locale, dopo che sono stati scaricati. Ci sono impostazioni di configurazione che vengono passate al sincronizzatore qui (come directory remota, timestamp, ecc.). Ma non esiste un'impostazione per il sincronizzatore equivalente all'impostazione precedente.

Tentativo di soluzione:

L'alternativa è creare il sincronizzatore come non-bean, creare FtpInboundFileSynchronizingMessageSourcein modo simile e utilizzare IntegrationFlows.from(source)per assemblare i risultati del sincronizzatore in un'eccezione di runtime quando il flusso viene registrato con il contesto del flusso:

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]

Ha senso; il FtpInboundFileSynchronizernon dovrebbe essere costruito al di fuori di un contesto. (Anche se questo sembra funzionare.) Ma come, in tal caso, posso assemblare dinamicamente flussi di integrazione ftp con un sincronizzatore configurato con un Comparator<FTPFile>?

Risposte

2 ArtemBilan Aug 24 2020 at 20:47

Sembra che non abbiamo esposto questa remoteComparatoropzione in DSL.

Sentiti libero di sollevare un problema di GH o persino di contribuire a risolverlo:https://github.com/spring-projects/spring-integration/issues

Come soluzione alternativa per i flussi dinamici, suggerirei davvero di andare in un separato FtpInboundFileSynchronizere FtpInboundFileSynchronizingMessageSourcequindi utilizzare il suddetto IntegrationFlows.from(source). Quello che probabilmente ti manca nella tua configurazione è questa 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);

Voglio dire che FtpInboundFileSynchronizingMessageSourceva bene passare a from()così com'è, ma synchronizerdeve essere aggiunto come bean extra per la registrazione.

Un altro modo più elegante è prendere in considerazione l'utilizzo di una nuova funzionalità chiamata estensioni DSL:https://docs.spring.io/spring-integration/docs/5.3.2.RELEASE/reference/html/dsl.html#java-dsl-extensions

Quindi, puoi estenderlo FtpInboundChannelAdapterSpecper fornire un'opzione mancante da configurare per un file synchronizer.