Introduzione a Spring Integration

1. Introduzione

Questo articolo introdurrà i concetti fondamentali di Spring Integration principalmente attraverso piccoli esempi pratici.

Spring Integration fornisce molti potenti componenti che possono migliorare notevolmente l'interconnettività di sistemi e processi all'interno di un'architettura aziendale.

Incarna alcuni dei modelli di design più raffinati e popolari, aiutando gli sviluppatori a evitare di creare i propri.

Daremo uno sguardo alle esigenze specifiche che questa libreria soddisfa in un'applicazione aziendale e perché è consigliabile rispetto ad alcune delle sue alternative. Analizzeremo anche alcuni strumenti disponibili per semplificare ulteriormente lo sviluppo di applicazioni basate su Spring Integration.

2. Configurazione

 org.springframework.integration spring-integration-core 4.3.5.RELEASE   org.springframework.integration spring-integration-file 4.3.5.RELEASE  

È possibile scaricare le ultime versioni di Spring Integration Core e Spring Integration File Support da Maven Central.

3. Il modello di messaggistica

Uno dei modelli fondamentali in questa libreria è la messaggistica. Il modello è incentrato sui messaggi: payload discreti di dati che si spostano da un sistema o processo di origine a uno o più sistemi o processi tramite canali predefiniti.

Storicamente, il modello è nato come il modo più flessibile per integrare più sistemi disparati in modo che:

  • Quasi completamente disaccoppia i sistemi coinvolti nell'integrazione
  • Consente ai sistemi partecipanti all'integrazione di essere completamente indipendenti gli uni dagli altri sottostanti protocolli, formattazione o altri dettagli di implementazione
  • Incoraggia lo sviluppo e il riutilizzo dei componenti coinvolti nell'integrazione

4. Integrazione della messaggistica in azione

Consideriamo un esempio di base che copia un file video MPEG da una cartella designata a un'altra cartella configurata:

@Configuration @EnableIntegration public class BasicIntegrationConfig{ public String INPUT_DIR = "the_source_dir"; public String OUTPUT_DIR = "the_dest_dir"; public String FILE_PATTERN = "*.mpeg"; @Bean public MessageChannel fileChannel() { return new DirectChannel(); } @Bean @InboundChannelAdapter(value = "fileChannel", poller = @Poller(fixedDelay = "1000")) public MessageSource fileReadingMessageSource() { FileReadingMessageSource sourceReader= new FileReadingMessageSource(); sourceReader.setDirectory(new File(INPUT_DIR)); sourceReader.setFilter(new SimplePatternFileListFilter(FILE_PATTERN)); return sourceReader; } @Bean @ServiceActivator(inputChannel= "fileChannel") public MessageHandler fileWritingMessageHandler() { FileWritingMessageHandler handler = new FileWritingMessageHandler(new File(OUTPUT_DIR)); handler.setFileExistsMode(FileExistsMode.REPLACE); handler.setExpectReply(false); return handler; } }

Il codice precedente configura un attivatore di servizi, un canale di integrazione e un adattatore di canale in entrata.

A breve esamineremo ciascuno di questi tipi di componenti in maggiore dettaglio. L' annotazione @EnableIntegration designa questa classe come una configurazione di Spring Integration.

Iniziamo il nostro contesto applicativo Spring Integration:

public static void main(String... args) { AbstractApplicationContext context = new AnnotationConfigApplicationContext(BasicIntegrationConfig.class); context.registerShutdownHook(); Scanner scanner = new Scanner(System.in); System.out.print("Please enter q and press  to exit the program: "); while (true) { String input = scanner.nextLine(); if("q".equals(input.trim())) { break; } } System.exit(0); }

Il metodo principale di cui sopra avvia il contesto di integrazione; accetta anche il carattere " q " immesso dalla riga di comando per uscire dal programma. Esaminiamo i componenti in modo più dettagliato.

5. Componenti di Spring Integration

5.1. Messaggio

L' interfaccia org.springframework.integration.Message definisce il messaggio di primavera: l'unità di trasferimento dei dati all'interno di un contesto di Spring Integration.

public interface Message { T getPayload(); MessageHeaders getHeaders(); }

Definisce le funzioni di accesso a due elementi chiave:

  • Intestazioni dei messaggi, essenzialmente un contenitore di valori-chiave che può essere utilizzato per trasmettere metadati, come definito nella classe org.springframework.integration.MessageHeaders
  • Il payload del messaggio, che è il dato effettivo che ha valore da trasferire - nel nostro caso d'uso, il file video è il payload

5.2. Canale

Un canale in Spring Integration (e in effetti, EAI) è l'impianto idraulico di base in un'architettura di integrazione. È il canale attraverso il quale i messaggi vengono inoltrati da un sistema all'altro.

Puoi pensarlo come un canale letterale attraverso il quale un sistema o processo integrato può inviare messaggi a (o ricevere messaggi da) altri sistemi.

I canali in Spring Integration sono disponibili in vari gusti, a seconda delle tue necessità. Sono ampiamente configurabili e utilizzabili immediatamente, senza alcun codice personalizzato, ma se hai esigenze personalizzate, è disponibile un framework robusto.

I canali punto-punto (P2P) vengono utilizzati per stabilire linee di comunicazione 1 a 1 tra sistemi o componenti. Un componente pubblica un messaggio sul canale in modo che un altro possa prenderlo. Può esserci un solo componente a ciascuna estremità del canale.

Come abbiamo visto, configurare un canale è semplice come restituire un'istanza di DirectChannel :

@Bean public MessageChannel fileChannel1() { return new DirectChannel(); } @Bean public MessageChannel fileChannel2() { return new DirectChannel(); } @Bean public MessageChannel fileChannel3() { return new DirectChannel(); }

Qui, abbiamo definito tre canali separati tutti identificati dal nome dei rispettivi metodi getter.

I canali di pubblicazione-sottoscrizione (Pub-Sub) vengono utilizzati per stabilire una linea di comunicazione uno-a-molti tra sistemi o componenti. Questo ci consentirà di pubblicare su tutti e 3 i canali diretti che abbiamo creato in precedenza.

Quindi, seguendo il nostro esempio, possiamo sostituire il canale P2P con un canale pub-sub:

@Bean public MessageChannel pubSubFileChannel() { return new PublishSubscribeChannel(); } @Bean @InboundChannelAdapter(value = "pubSubFileChannel", poller = @Poller(fixedDelay = "1000")) public MessageSource fileReadingMessageSource() { FileReadingMessageSource sourceReader = new FileReadingMessageSource(); sourceReader.setDirectory(new File(INPUT_DIR)); sourceReader.setFilter(new SimplePatternFileListFilter(FILE_PATTERN)); return sourceReader; } 

Ora abbiamo convertito l'adattatore del canale in entrata per pubblicare su un canale Pub-Sub. Questo ci consentirà di inviare i file che vengono letti dalla cartella di origine a più destinazioni.

5.3. ponte

Un bridge in Spring Integration viene utilizzato per collegare due canali di messaggi o adattatori se per qualsiasi motivo non possono connettersi direttamente.

In our case, we can use a bridge to connect our Pub-Sub channel to three different P2P channels (because P2P and Pub-Sub channels can't be connected directly):

@Bean @BridgeFrom(value = "pubSubFileChannel") public MessageChannel fileChannel1() { return new DirectChannel(); } @Bean @BridgeFrom(value = "pubSubFileChannel") public MessageChannel fileChannel2() { return new DirectChannel(); } @Bean @BridgeFrom(value = "pubSubFileChannel") public MessageChannel fileChannel3() { return new DirectChannel(); }

The above bean configuration now bridges the pubSubFileChannel to three P2P channels. The @BridgeFrom annotation is what defines a bridge and can be applied to any number of channels that need to subscribe to the Pub-Sub channel.

We can read the above code as “create a bridge from the pubSubFileChannel to fileChannel1, fileChannel2, and fileChannel3 so that messages from pubSubFileChannel can be fed to all three channels simultaneously.”

5.4. Service Activator

The Service Activator is any POJO that defines the @ServiceActivator annotation on a given method. This allows us to execute any method on our POJO when a message is received from an inbound channel, and it allows us to write messages to an outward channel.

In our example, our service activator receives a file from the configured input channel and writes it to the configured folder.

5.5. Adapter

The Adapter is an enterprise integration pattern-based component that allows one to “plug-in” to a system or data source. It is almost literally an adapter as we know it from plugging into a wall socket or electronic device.

It allows reusable connectivity to otherwise “black-box” systems like databases, FTP servers and messaging systems such as JMS, AMQP, and social networks like Twitter. The ubiquity of the need to connect to these systems means that adapters are very portable and reusable (in fact there's a small catalog of adapters, freely available and ready to use by anyone).

Adapters fall into two broad categories — inbound and outbound.

Let's examine these categories in the context of the adapters in use in our sample scenario:

Inbound adapters, as we have seen, are used to bring in messages from the external system (in this case a filesystem directory).

Our inbound adapter configuration consists of:

  • An @InboundChannelAdapter annotation that marks the bean configuration as an adapter — we configure the channel to which the adapter will feed its messages (in our case, an MPEG file) and a poller, a component which helps the adapter poll the configured folder at the specified interval
  • A standard Spring java configuration class that returns a FileReadingMessageSource, the Spring Integration class implementation that handles filesystem polling

Outbound adapters are used to send messages outwards. Spring Integration supports a large variety of out-of-the-box adapters for various common use cases.

6. Conclusion

Abbiamo esaminato un caso d'uso di base con Spring Integration che dimostra la configurazione basata su Java della libreria e la riusabilità dei componenti disponibili.

Il codice Spring Integration è distribuibile come progetto autonomo all'interno di JavaSE e come parte di qualcosa di più grande in un ambiente Jakarta EE. Sebbene non sia direttamente in concorrenza con altri prodotti e modelli incentrati sull'EAI come gli Enterprise Service Bus (ESB), è un'alternativa praticabile e leggera per risolvere molti degli stessi problemi per cui sono stati creati gli ESB.

Puoi trovare il codice sorgente per questo articolo nel progetto Github.