How Does Spring Cloud Stream’s Built‑In Retry Handle Message Failures?
This article explains Spring Cloud Stream’s default retry mechanism, demonstrates a complete example of producing and consuming messages with intentional failures, shows how to configure retry attempts, and discusses what happens when retries succeed or ultimately fail, providing practical guidance for reliable message processing.
Previously I wrote about common issues when using Spring Cloud Stream, such as handling duplicate consumption and consuming messages produced by oneself. In the next few days I will focus on how to deal with message consumption failures.
Application Scenario
Retry can solve failures caused by external factors like network glitches when calling a Web Service after receiving a message. By retrying the consumer logic, the next attempt may succeed and complete the business action.
Hands‑On Example
Below is a minimal Spring Boot application that demonstrates the default retry mechanism. It includes a producer endpoint and a consumer that deliberately throws an exception to simulate failure.
@EnableBinding(TestApplication.TestTopic.class)
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@RestController
static class TestController {
@Autowired
private TestTopic testTopic;
@GetMapping("/sendMessage")
public String messageWithMQ(@RequestParam String message) {
testTopic.output().send(MessageBuilder.withPayload(message).build());
return "ok";
}
}
@Slf4j
@Component
static class TestListener {
@StreamListener(TestTopic.INPUT)
public void receive(String payload) {
log.info("Received: " + payload);
throw new RuntimeException("Message consumer failed!");
}
}
interface TestTopic {
String OUTPUT = "example-topic-output";
String INPUT = "example-topic-input";
@Output(OUTPUT)
MessageChannel output();
@Input(INPUT)
SubscribableChannel input();
}Running the application and calling http://localhost:8080/sendMessage?message=hello produces three "Received: hello" logs, after which the consumer finally throws an exception.
Configuration
Spring Cloud Stream retries three times by default. You can change the number of attempts with:
spring.cloud.stream.bindings.example-topic-input.consumer.max-attempts=1For pure computational logic where retries are useless, set the value to 0 to avoid unnecessary delays.
Deep Thinking
Question 1: If a retry eventually succeeds, will an exception still be logged?
Answer: No. A successful retry marks the whole consumption as successful, so no error is recorded.
To verify, modify the listener to count attempts and only throw an exception on the first two attempts:
@Slf4j
@Component
static class TestListener {
int counter = 1;
@StreamListener(TestTopic.INPUT)
public void receive(String payload) {
log.info("Received: " + payload + ", " + counter);
if (counter == 3) {
counter = 1;
return;
} else {
counter++;
throw new RuntimeException("Message consumer failed!");
}
}
}Running this version shows three logs with counters 1, 2, 3 and no error stack trace.
Question 2: What should be done when all retries fail?
Currently the only option is to log the exception and alert operators, who can then take remedial actions based on the logged message details. More sophisticated handling (e.g., dead‑letter queues) would require additional configuration.
--- End of technical guide ---
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
