Spring Boot e RabbitMQ
Per utilizzare RabbitMQ in un progetto Spring Boot occorre aggiungere lo starter AMQP visto che si tratta di un message broker AMQP compliant.
Per un progetto preimpostato si può aggiungere al file pom.xml il seguente blocco
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
Con questa dipendenza verrà configurata in automatico una connessione al server RabbitMQ.
Di default le credenziali di accesso sono guest/guest ma è possibile impostare una nuova utenza.
Nel nostro caso utilizzeremo un'istanza locale del broker gestita attraverso un file docker-compose.yaml (che è possibile scaricare da questo link) con le seguenti impostazioni che andranno specificate nel file application.properties.
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=rabbitpwd
Vediamo ora quali modifiche sono necessarie all'applicazione.
Prima di tutto dobbiamo creare una queue (coda): ciò può essere fatto direttamente all'interno della console di gestione di RabbitMQ oppure affidando questo compito a Spring Boot.
In quest'ultimo caso ci serve un opportuno bean in grado di restituire appunto un oggetto Queue
. L'unico parametro obbligatorio del costruttore è il nome della coda.
@Bean
public Queue demoQueue() {
return new Queue("test");
}
La definizione del bean è inserita all'interno di una classe annotata con @Configuration
.
Se la coda è già presente sul server RabbitMQ ma differisce per le proprietà impostate sarà generato un errore
reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'durable' for queue 'hello' in vhost '/'
Per la pubblicazione dei messaggi utilizziamo il RabbitTemplate (simile al RestTemplate e al JdbcTemplate) che iniettiamo all'interno di una classe Publisher
annotata con @Service
o in alternativa con @Component
affinchè Spring Boot generi un bean all'avvio dell'applicazione.
@Service
public class Publisher {
@Autowired
private RabbitTemplate rabbitTemplate;
@Scheduled(fixedDelay = 5000)
public void publishMessage() {
String message = "Message published on " + LocalDateTime.now();
rabbitTemplate.convertAndSend("test", message);
}
}
Per simulare l'invio dei messaggi utilizziamo l'annotazione @Scheduled
che chiama il metodo publishMessage()
ogni 5 secondi.
Per abilitare lo scheduling occorre aggiungere l'annotazione @EnableScheduling
alla classe principale del progetto.
N.B. Per maggiori dettagli sullo scheduling dei task si rimanda a questo video dettagliato.
Il messaggio mostra semplicemente l'ora in cui è stato generato ed inviato, ma in scenari di produzione può contenere qualsiasi informazione più complessa.
L'effettiva spedizione del messaggio si ottiene richiamando il metodo convertAndSend("test", message)
del RabbitTemplate specificando il nome della queue a cui indirizzarlo.
Eseguendo l'applicazione configurata
mvn spring-boot:run
è possibile visualizzare la sequenza dei messaggi inviati all'interno della dashboard di RabbitMQ a cui possiamo collegarci
Vediamo ora come è possibile "consumare" i messaggi presenti nella coda.
In questo caso realizziamo una semplice classe service Consumer
da annotare con @RabbitListener(queues = "test")
in modo da specificare la queue su cui mettersi in ascolto.
Il metodo destinato a recuperare i messaggi dalla coda é annotato con @RabbitHandler
ed ha un unico parametro di tipo stringa corrispondente proprio al messaggio da elaborare.
@Service
@RabbitListener(queues = "test")
public class Consumer {
public static final Logger logger = LoggerFactory.getLogger(Consumer.class);
@RabbitHandler
public void readMessage(String message) {
logger.warn("From Queue : {}", message);
}
}
Anche in questo caso possiamo eseguire l'applicazione e osservare nei log la sequenza dei messaggi processati secondo l'ordine di arrivo.
[VIDEO]
[LINKS]
- Tutorial di Spring Boot - Indice argomenti
- Esercitazioni di Spring Boot - Indice argomenti
- Codice su GitHub
- Flashcards Anki per lo studio
- Libri consigliati