Spring Apache Kafka onFailure Callback of KafkaTemplate not fired on connection error
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Apache Kafka, a distributed streaming platform, is widely used for handling real-time data feeds. Kafka provides fault tolerance, scalability, and high throughput, making it ideal for applications like logging, monitoring, and event sourcing. The KafkaTemplate in Spring Framework aids in integrating Kafka with Spring applications, offering a straightforward approach to sending messages to a Kafka topic.
Understanding KafkaTemplate and onFailure Callback
KafkaTemplate is part of the Spring Kafka project and simplifies sending messages to Kafka topics. A key feature of KafkaTemplate is its asynchronous send method, which returns a ListenableFuture. You can attach a callback to this future to handle success (onSuccess) and failure scenarios (onFailure).
The onFailure callback is designed to trigger when there are exceptions during the message publishing process. For example, if the Kafka broker cannot serialize a message or if a required topic is missing, the onFailure callback is expected to handle such errors. The typical usage looks like this:
Issue: onFailure Callback Not Fired on Connection Errors
Despite its robust design, many developers encounter a scenario where the onFailure callback does not fire during Kafka connection issues. This can be a significant issue as it may give the false impression that messages are being sent when, in fact, they might not be due to network or broker connectivity issues.
Why does this happen?
The root cause of this issue lies in the asynchronous nature of the KafkaTemplate send operation. When KafkaTemplate.send() is invoked, it returns immediately with a ListenableFuture. The actual sending of the message to the Kafka broker occurs in a different thread. If Kafka is not reachable at that moment (e.g., network issues, broker down), the Producer will retry based on its configuration (retries and retry.backoff.ms settings).
The onFailure callback is only called if an exception is caught during these retries or if an irrecoverable error occurs after all retries are exhausted. However, in some configurations or transient network issues, retries might keep happening without an immediate exception, delaying the invocation of onFailure.
How to Handle These Scenarios
To better manage these scenarios, consider the following approaches:
- Configure Producer Retries and Timeout: Set appropriate values for
retriesandretry.backoff.msin your Kafka producer configuration. Adjusting these settings can help in firing failure callbacks after all retries are exhausted. - Logging and Monitoring: Implement logging in the callback methods to monitor message delivery and failures. Also, consider using a monitoring tool to watch the Kafka cluster’s health.
- Custom Error Handling Logic: Implement custom error handling to deal with specific scenarios where the onFailure callback does not meet your requirements.
Summary Table
| Aspect | Description |
| KafkaTemplate | Facilitates sending messages to Kafka within Spring applications. |
| onFailure Callback | Handles failures during message sending but may not fire for network issues initially due to retries. |
| Issue Resolution | Adjust producer settings, enhance monitoring, and customize error handling. |
Conclusion
Understanding the behavior of KafkaTemplate and its callbacks is crucial for designing robust Kafka-based applications. While the onFailure callback is a powerful feature, recognizing its limitations and handling exceptions appropriately can help prevent data loss and ensure message delivery even in the face of transient network issues or Kafka broker downtimes.
Related reading
- Spring Boot + Kafka + Kerberos configuration
- Spring Boot / Kafka Json Deserialization - Trusted Packages
- Spring Boot & Kafka, Producer thrown exception with key=''null''
- Spring Boot auto configuration of Kafka Producers with multiple De-Serializer types
- Spring as Broker Relay by using an external Message Broker
- Spring Async - no data found in integration test
- Spring Boot - Cannot determine embedded database driver class for database type NONE
- Spring Boot - Cannot determine embedded database driver class for database type NONE

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseSystem Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.