Spring Kafka
Multiple Listeners
ApplicationContext
Kafka Listeners
Object Management

Spring Kafka Multiple Listeners for different objects within an ApplicationContext

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Apache Kafka is a popular distributed streaming platform that enables you to build robust messaging solutions. With an integration library like Spring Kafka, developers can more easily incorporate Kafka within their Spring applications. A common requirement in these applications is to have multiple listener methods that consume different types of messages from various Kafka topics. Understanding how to correctly configure and use multiple Kafka listeners within the same Spring ApplicationContext can greatly enhance your application's responsiveness and scalability.

Overview of Kafka Listeners in Spring

Spring Kafka provides @KafkaListener annotation, which is used to mark a method to be the target of a Kafka message listener on the specified topics. The basic usage involves annotating a method of a managed bean with @KafkaListener and setting the topics or topicPattern attribute to define what topics this listener should subscribe to.

Here is a simple example:

java
1@Component
2public class MessageListener {
3    
4    @KafkaListener(topics = "simpleMessageTopic")
5    public void processMessage(String message) {
6        System.out.println("Received message: " + message);
7    }
8}

Configuring Multiple Listeners

Configuring multiple listeners in the same application context involves declaring multiple methods with the @KafkaListener annotation, potentially listening to different topics or using different consumer configurations.

Example: Multiple Listeners for Different Topics

Below is an example showing two listeners configured to listen to different topics within the same class:

java
1@Component
2public class MultiTopicListener {
3
4    @KafkaListener(topics = "topic1")
5    public void listenerForTopic1(String message) {
6        System.out.println("Received message on topic 1: " + message);
7    }
8
9    @KafkaListener(topics = "topic2")
10    public void listenerForTopic2(String message) {
11        System.out.println("Received message on topic 2: " + message);
12    }
13}

Example: Different Data Types

If the messages on different topics are of different data types, Spring's message conversion can be leveraged. By configuring appropriate message converters, each listener method can accept a message already converted to the correct type:

java
1@Component
2public class TypedListener {
3
4    @KafkaListener(topics = "stringTopic")
5    public void handleString(String message) {
6        System.out.println("Handle string message: " + message);
7    }
8
9    @KafkaListener(topics = "jsonTopic", containerFactory = "kafkaJsonContainerFactory")
10    public void handleJson(JsonNode message) {
11        System.out.println("Handle JSON message: " + message);
12    }
13}

Essential Configuration

Handling multiple types of messages and complex configurations often requires defining multiple KafkaListenerContainerFactory beans that configure the specifics of message listener containers for different scenarios.

The following snippet shows how to define a container factory for JSON messages:

java
1@Configuration
2public class KafkaListenerConfig {
3
4    @Bean
5    public ConcurrentKafkaListenerContainerFactory<String, JsonNode> kafkaJsonContainerFactory(
6            ConsumerFactory<String, JsonNode> consumerFactory) {
7        ConcurrentKafkaListenerContainerFactory<String, JsonNode> factory = new ConcurrentKafkaListenerContainerFactory<>();
8        factory.setConsumerFactory(consumerFactory);
9        return factory;
10    }
11
12   // Other configurations
13}

Summary Table

Here's a summary of key aspects to consider when setting up multiple Kafka listeners:

FeatureDescription
Multiple MethodsUse multiple @KafkaListener methods in the same or different beans.
Topic ConfigurationConfigure each listener to subscribe to specific topics.
Data Type HandlingUse different container factories to handle various data formats.
@KafkaListener EssentialsUtilize attributes like containerFactory to specify which listener container should be used.

Additional Considerations

  • Error Handling: Customize error handling strategies per listener by setting the errorHandler attribute on the @KafkaListener.
  • Concurrency: Configure the concurrency setting in the ConcurrentKafkaListenerContainerFactory to handle more messages concurrently.
  • Ordering and Partitions: Ensure understanding of how Kafka partitions and consumer groups affect message order and processing.

Thorough configuration and understanding of Spring Kafka's facilities can make your application robust, scalable, and responsive, allowing you to effectively handle diverse data streams coming from different Kafka topics.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design