Spring Boot RabbitMQ Multiple Queues Example

– Tutorial: “Spring Boot Rabbitmq Multiple Queues Example using RabbitMq Exchange to Exchange Topology – Spring Boot Rabbitmq Multiple Listeners”

In the post, I show you how to work with SpringBoot RabbitMq Exchange to Exchange Topology to develop an example “Rabbitmq Multiple Queues and Multiple Listeners”.

* Technologies:

– Java 8
– Maven
– Spring Tool Suite
– Spring Boot
– RabbitMq

RabbitMq Exchange to Exchange – Spring Boot Rabbitmq Multiple Queues Example

We create a RabbitMQ topology with 2 topic exchanges and 3 binding queues:

Spring Boot Rabbitmq Multiple Queue - with Exchange Topic Architecture
Spring Boot Rabbitmq Multiple Queue – with Exchange Topic Architecture

Scenarios with above design:
– when we send a message with routing key: sys.prod.info, it will be delivered by path: X1 -> Q3.
– when we send a message with routing key: app.prod.error, it will be delivered by path: X1 -> X2 -> {Q2, Q3}.
– when we send a message with routing key: sys.test.error, it will be delivered by path: X1 -> X2 -> Q1.

Practices – Spring Boot Rabbitmq Multiple Queues Example

In the tutorial, we create 2 SpringBoot project as below:

Spring Boot RabbitMQ Topic - Project Structure
Spring Boot RabbitMQ Topic – Project Structure

– Step to do:
– Create SpringBoot projects
– Define data model
– Implement RabbitMq Producer
– Implement RabbitMq consumer
– Run and check results

Create SpringBoot projects

Using SpringToolSuite, create 2 SpringBoot projects, then add need dependency spring-boot-starter-amqp:


<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

Define Spring Data Model – Spring Boot RabbitMQ Multiple Queues Example

Create Log data model for both projects:


package com.loizenai.rabbitmq.model;
 
public class Log {
	private String content;
	private String routingKey;
	
	public Log(){};
	
	public Log(String content, String routingKey){
		this.content = content;
		this.routingKey = routingKey;
	}
	
	public String getContent(){
		return this.content;
	}
	
	public void setContent(String content){
		this.content = content;
	}
	
	public String getRoutingKey(){
		return this.routingKey;
	}
	
	public void setRoutingKey(String routingKey){
		this.routingKey = routingKey;
	}
	
	@Override
	public String toString() {
		return String.format("{content = %s, routingKey = %s}", content, routingKey);
	}
}

Now it’s time for implementation. Let’s go!

Configure SpringBoot RabbitMq Producer – Spring Boot RabbitMQ Multiple Queues Example


package com.loizenai.rabbitmq.config;
 
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class RabbitMqConfig {
	
    @Bean
    public MessageConverter jsonMessageConverter(){
        return new Jackson2JsonMessageConverter();
    }
    
    public AmqpTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(jsonMessageConverter());
        return rabbitTemplate;
    }
}

Open application.properties, add configuration:


spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
jsa.rabbitmq.exchange=jsa.exchange.logs
jsa.rabbitmq.queue=jsa.queue
jsa.rabbitmq.routingkey=jsa.routingkey

Implement SpringBoot RabbitMq Producer


package com.loizenai.rabbitmq.producer;
 
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
import com.loizenai.rabbitmq.model.Log;
 
@Component
public class Producer {
	
	@Autowired
	private AmqpTemplate amqpTemplate;
	
	@Value("${jsa.rabbitmq.exchange}")
	private String exchange;
	
	public void produce(Log logs){
		String routingKey = logs.getRoutingKey();
		amqpTemplate.convertAndSend(exchange, routingKey, logs);
		System.out.println("Send msg = " + logs);
	}
}

Implement SpringBoot RabbitMQ Producer Client


package com.loizenai.rabbitmq;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
import com.loizenai.rabbitmq.model.Log;
import com.loizenai.rabbitmq.producer.Producer;
 
@SpringBootApplication
public class SpringRabbitMqProducerApplication  implements CommandLineRunner{
 
	public static void main(String[] args) {
		SpringApplication.run(SpringRabbitMqProducerApplication.class, args);
	}
	
	@Autowired
	Producer producer;
 
	@Override
	public void run(String... args) throws Exception {
		
		/**
		 *  1
		 */
		String content = "2014-03-05 10:58:51.1  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52";
		String routingKey = "sys.dev.info";
		
		// send to RabbitMQ
		producer.produce(new Log(content, routingKey));
		
		/**
		 *  2
		 */
		content = "2017-10-10 10:57:51.10 ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]";
		routingKey = "sys.test.error";
		
		// send to RabbitMQ
		producer.produce(new Log(content, routingKey));
		
		/**
		 *  3
		 */
		content = "2017-10-10 10:57:51.112  ERROR java.lang.Exception: java.lang.Exception";
		routingKey = "app.prod.error";
		
		// send to RabbitMQ
		producer.produce(new Log(content, routingKey));
	}
}

Configure SpringBoot RabbitMQ Consumer


package com.loizenai.rabbitmq.config;
 
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class RabbitMqConfig {
	
    @Bean
    public MessageConverter jsonMessageConverter(){
        return new Jackson2JsonMessageConverter();
    }
    
    @Bean
    public SimpleRabbitListenerContainerFactory jsaFactory(ConnectionFactory connectionFactory,
            SimpleRabbitListenerContainerFactoryConfigurer configurer) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setMessageConverter(jsonMessageConverter());
        return factory;
    }
}

Open application.properties, add configuration:


spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
jsa.rabbitmq.queue=jsa.queue.logs.application-error
#jsa.rabbitmq.queue=jsa.queue.logs.system-error
#jsa.rabbitmq.queue=jsa.queue.logs.production

Implement SpringBoot RabbitMQ Consumer


package com.loizenai.rabbitmq.consumer;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import com.loizenai.rabbitmq.model.Log;

@Component
public class Consumer {
	
    @RabbitListener(queues="${jsa.rabbitmq.queue}", containerFactory="jsaFactory")
    public void recievedMessage(Log logs) {
        System.out.println("Recieved Message: " + logs);
    }
}

Run and Check Results

– Setup RabbitMq exchange, queues:

Enable rabbitmq_management by cmd: rabbitmq-plugins enable rabbitmq_management --online. Then go to: http://localhost:15672 -> login with user/password: guest/guest.

– Add RabbitMQ exchanges:

Go to http://localhost:15672/#/exchanges, add 2 exchanges: {jsa.exchange.logs, jsa.exchange.logs.error}.

Spring Boot RabbitMQ Topic Connection
Spring Boot RabbitMQ Topic Connection

– Add RabbitMQ Queue:

Go to http://localhost:15672/#/queues, add 3 queues: {jsa.queue.logs.application-error, jsa.queue.logs.system-error, jsa.queue.logs.production}.

Spring Boot Rabbitmq Topic Create Exchange
Spring Boot Rabbitmq Topic Create Exchange

– Binding the queues & exchanges:

Spring Boot RabbitMQ Topic 2 Queue 1
Spring Boot RabbitMQ Topic 2 Queue 1
SpringBoot RabbitMQ Topic Exchange Bindling
SpringBoot RabbitMQ Topic Exchange Bindling

– Run SpringBoot-RabbitMQ-Producer with commandline mvn spring-boot:run,

-> Console’s logs:


Send msg = {content = 2014-03-05 10:58:51.1  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52, routingKey = sys.prod.info}
Send msg = {content = 2017-10-10 10:57:51.10 ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]], routingKey = sys.test.error}
Send msg = {content = 2017-10-10 10:57:51.112  ERROR java.lang.Exception: java.lang.Exception, routingKey = app.prod.error}

– See queues’ status:

Springboot Rabbitmq Topic After Consume in jsa_logs_sys
Springboot Rabbitmq Topic After Consume in jsa_logs_sys

– Run SpringBoot-RabbitMQ-Consumer which listen to jsa.queue.logs.application-error queue with configuration:

jsa.rabbitmq.queue=jsa.queue.logs.application-error:

– Console’s logs:


Recieved Message: {content = 2017-10-10 10:57:51.112  ERROR java.lang.Exception: java.lang.Exception, routingKey = app.prod.error}

– Run SpringBoot-RabbitMQ-Consumer which listen to jsa.queue.logs.system-error queue with configuration:

jsa.rabbitmq.queue=jsa.queue.logs.system-error:

-> Console’s logs:


Recieved Message: {content = 2017-10-10 10:57:51.10 ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]], routingKey = sys.test.error}

– Run SpringBoot-RabbitMQ-Consumer which listen to jsa.queue.logs.production queue with configuration:

jsa.rabbitmq.queue=jsa.queue.logs.production:

– Console’s logs:


Recieved Message: {content = 2014-03-05 10:58:51.1  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52, routingKey = sys.prod.info}
Recieved Message: {content = 2017-10-10 10:57:51.112  ERROR java.lang.Exception: java.lang.Exception, routingKey = app.prod.error}

Read More

Related posts:


– Reference Link: RabbitMQ Exchange Topic

SourceCode

SpringBoot-RabbitMQ-Producer
SpringBoot-RabbitMQ-Consumer

Spring Boot and Spring Batch Integration Example

– Tutorial “Spring Boot and Spring Batch Integration Example – Import CSV data to PostgreSQL database using Spring Batch Job”

Spring Batch is a powerful module to implement a batch process for tons of data conveniently. This tutorial guide you how to import CSV Data to PostgreSQL Database using Spring Batch Job.

Continue reading “Spring Boot and Spring Batch Integration Example”

Spring Boot JPA One-to-Many Example Rest

Tutorial: “Spring Boot JPA One-to-Many Example Rest – Spring JPA/Hibernate One-to-Many Association + PostgreSQL | SpringBoot CRUD RestAPIs Post/Get/Put/Delete example”

In the tutorial, we show how to expose CRUD RestAPIs Post/Get/Put/Delete to interact with Hibernate Spring JPA One-to-Many association models using SpringBoot and PostgreSQL database.

Continue reading “Spring Boot JPA One-to-Many Example Rest”

Spring Boot One to One Mapping Example

Tutorial: “Spring Boot One to One Mapping Example – Spring Crud Example using One to One Mapping”

In the tutorial, we show how to expose Crud RestAPIs Post/Get/Put/Delete to interact with Hibernate Spring JPA One-to-One relationship models using SpringBoot and PostgreSQL database.

Continue reading “Spring Boot One to One Mapping Example”