Configuring automatic message retry using RabbitMQ and Spring Boot

Marcos
Javarevisited
Published in
3 min readJun 19, 2022

--

In some specific situations where we are consuming messages from a queue, we may want those messages not to leave that queue if something specific has not yet happened. It got pretty abstract, right? I’ll try an example:

Imagine that a purchase was made on a website.

Now imagine that an email must be sent after the product is separated from stock.

But this email should only be sent if a condition is met and that condition is the separation of the product there in stock.

Don’t ask me if this makes sense from a business point of view, it’s just a situation to justify the retry lol.

A simple drawing would look like this:

And what would it look like in a spring boot application?

Let’s do this:

pom.xml:

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

application.properties:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.initial-interval=5000 // the first time will wait 5 seconds to try again
spring.rabbitmq.listener.simple.retry.max-attempts=10 //will try a maximum of 10 times
spring.rabbitmq.listener.simple.retry.max-interval=300000 // the maximum interval between attempts is 5 minutes
spring.rabbitmq.listener.simple.retry.multiplier=3.0 // multiplies the range by 3

queue.name=test //queue name

Listener:

@Component
public class QueueConsumer {

@RabbitListener(queues = {"${queue.name}"})
public void receive(@Payload String fileBody) throws BusinessException {
System.out.println("Message " + fileBody + LocalDateTime.now());

if(Integer.parseInt(fileBody) == 1){
throw new BusinessException("testing for exception");
}

}

}

Main class:

@EnableRabbit
@SpringBootApplication
public class AppApplication {

public static void main(String[] args) {
SpringApplication.run(AppApplication.class, args);
}

}

Okay, that’s all we need to test this. In the first message I sent the value 2:

Then it was consumed and removed from the queue.

In the second I sent the value 1 and it will be returned to the queue because an exception happened:

Look at the intervals:

This already gives us a cool proof of concept to solve some problems.

From here, just put this according to the situations that appear in each project.

--

--

Marcos
Javarevisited

I study software development and I love memes.