As we are already aware, there are four types of RabbitMQ message exchanges are available. They can be listed as follows.
- Direct Exachange
- Topic Exchange
- Fanout Exchange
- Header Exchange
In this Article, we are going to look at Topic exchange.
What is Topic Exchange?
Same as Direct, but wildcards are allowed in the binding key. ‘#‘ matches zero or more dot-delimited words and ‘*‘ matches exactly one such word.
- * (star) can substitute for exactly one word.
- # (hash) can substitute for zero or more words.
Topic exchanges route messages to one or many queues based on matching between a message routing key and the pattern that was used to bind a queue to an exchange. The topic exchange type is often used to implement various publish/subscribe pattern variations. Topic exchanges are commonly used for the multicast routing of messages.
Here is what we are going to do

In this example we are trying to sort the messages and direct into the right queue based on the manufacturer of the car. we will be getting a huge amount of messages about registered cars in the city. The routing key pattern of every message is as follows.
manufacturer_name.car.type
As you can see, we have created a Topic exchange called vehicle_exchange. In addition, we have created three queues and bound them to the Topic exchange (vehicle_exchange) with following binding keys.
- toyota_cars_queue ( binding key – toyota.cars.* )
toyota_cars_queue is bound to the exchange with wildcard biding key toyota.cars.* This means that the any message starting with routing key toyota.cars and ending with exactly any text should be directed to this queue (toyota_cars_queue).
- nissan_cars_queue ( binding key – nissan.cars.* )
In the same way, any message starting with routing key nissan.cars and ending with exactly any text should be directed to the nissan_cars_queue.
- all_cars_queue ( binding key – *.cars.#)
According to the binding key, the routing key should start with any text (exactly one) and followed by cars keyword. it can be ended with zero or more texts.
e.g:- The following set of routing keys can be identified as valid routing key for this binding pattern.
nissan.cars , toyota,cars , any.cars , anything.cars.everything , anything.cars.anything.and.everything
The following table will show you a list of routing keys and their destination queue(s)
routing key |
delivered to queue(s) |
nissan.cars.japan |
nissan_cars_queue and all_cars_queue |
nissan.cars |
all_cars_queue |
toyota.cars.japan.manufactured |
all_cars_queue |
japan.toyota.cars |
No matching queue. message will be discard |
import.nissan.cars.from.japan |
No matching queue. message will be discard |
toyota.cars.manufatured |
toyota_cars_queue and all_cars_queue |
no.latest.cars.toyota |
No matching queue. message will be discard |
Now i believe that you have a clear understanding of how these wildcard binding keys are working with topic exchange.
Topic exchange : More to consider
Topic exchange is powerful and can behave like other exchanges.
When a queue is bound with “#” (hash) binding key – it will receive all the messages, regardless of the routing key – like in fanout exchange.
When special characters “*” (star) and “#” (hash) aren’t used in bindings, the topic exchange will behave just like a direct one.
Setting UP RabbitMQ Server

- Creating the toyota_cars_queue and bind it to the vehicle_exchange.


- Creating the nissan_cars_queue and bind it to the vehicle_exchange.


- Creating the all_cars_queue and binding it to the vehicle_exchange


Now we have created all three queues and bound them to the Topic exchange that we have created. Now it is the time to develop a publisher and subscriber application for publish and receive messages from this RabbitMQ server set up.
Producer and Consumer Application
Before moving forward, i need to inform you that the fully source code for the Producer and Consumer application can be found at GitHub. You may clone the source code and continue with the article.
click here to download the source code of the application
Producer Application
Here is the project structure of the Producer Application.

first make sure that you have defined the valid RabbitMQ server details in the application.properties file. These information will be used by the ConnectionFactory class to make a connection with RabbitMQ server when the RabbitTemplate is used.
|
spring.rabbitmq.host=localhost |
|
spring.rabbitmq.port=5672 |
|
spring.rabbitmq.username=guest |
|
spring.rabbitmq.password=guest |
Now check whether you have declared/configured the required beans to use Spring AMQP feature with RabbitMQ.
|
package com.springbootdev.examples.producer.config; |
|
|
|
import org.springframework.amqp.rabbit.connection.ConnectionFactory; |
|
import org.springframework.amqp.rabbit.core.RabbitTemplate; |
|
import org.springframework.amqp.support.converter.*; |
|
import org.springframework.context.annotation.Bean; |
|
import org.springframework.context.annotation.Configuration; |
|
|
|
|
|
@Configuration |
|
public class RabbitMqConfig |
|
{ |
|
@Bean |
|
public MessageConverter messageConverter() |
|
{ |
|
return new Jackson2JsonMessageConverter(); |
|
} |
|
|
|
@Bean |
|
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { |
|
RabbitTemplate template = new RabbitTemplate(connectionFactory); |
|
template.setMessageConverter(messageConverter()); |
|
return template; |
|
} |
|
} |
As i have mentioned earlier, ConnectionFactory will use the RabbitMQ server details declared in the application.properties to make a connection with RabbitMQ server when the RabbitTemplate is used.
We will be trying to send the POJO instance ( Car object) as the message body. we cannot send it as a java object and we need to convert it into some other common exchange format. We have chosen the JSON as the common exchange format and RabbitTemplate will use the Jackson2JsonMessageConverter as a the message converter for converting the POJO into the JSON format.
Now we will look at the ProducerService
|
package com.springbootdev.examples.producer.service; |
|
|
|
import com.springbootdev.examples.producer.model.Car; |
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
import org.springframework.amqp.rabbit.core.RabbitTemplate; |
|
import org.springframework.beans.factory.annotation.Autowired; |
|
import org.springframework.stereotype.Service; |
|
|
|
@Service |
|
public class ProducerService { |
|
|
|
@Autowired |
|
private RabbitTemplate rabbitTemplate; |
|
|
|
private static final String EXCHANGE_NAME = "vehicle_exchange"; |
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ProducerService.class); |
|
|
|
private String[] routeKeys = new String[]{ |
|
"nissan.cars.japan", |
|
"nissan.cars", |
|
"toyota.cars.japan.manufactured", |
|
"japan.toyota.cars", |
|
"import.nissan.cars.from.japan", |
|
"toyota.cars.manufatured", |
|
"no.latest.cars.toyota" |
|
}; |
|
|
|
public void produce() { |
|
for (String routingKey : routeKeys) { |
|
logger.info(" sending the message with routing key {}", routingKey); |
|
|
|
Car car = new Car(routingKey); |
|
rabbitTemplate.convertAndSend(EXCHANGE_NAME, routingKey, car); |
|
} |
|
} |
|
} |
As per the above table. we are having seven routing keys and we are going to publish messages with those routing keys to the exchange called “vehicle_exchange“. When you run the Producer application, the output will be something like below.
mvn spring-boot:run

Now all the messages are published to the RabbitMQ server. So we can check whether the messages are delivered to the relevant queues.

Now we are done with the Producer application for publishing messages for RabbitMQ Topic exchange. Fully source code (both producer and consumer) of this article can be found at GitHub. If you need further explanation of writing RabbitMQ consumer application, it is highly recommended to look at one of the below articles.