Fredrik Enetorp
Fredrik Enetorp

Reputation: 425

Use KafkaListener in class not managed by Spring

In my project, I have a lot of spring managed components that does about the same thing. I want to create a common Util class that does all the common operations for all my components. Since this Util class needs to access environment variables and beans it's instantiated like this:

// Util class:
public class FooUtil {
    public FooUtil(Environment env) {
        env.getProperty("FOO_TOPIC", "foo")
    }
}

// Example configuration for one of my components:
@Configuration
public class ComponentConfig {
    @Bean
    FooUtil fooUtil(Environment env) {
        return new FooUtil(env);
    }
}

This allows FooUtil to access all environment variables and beans without itself being a component.

Now, this Util class also need to listen to kafka topics. Each component currently has a listener set up like this:

@KafkaListener(topics = "${FOO"_TOPIC:foo2}", containerFactory = "kafkaListenerContainerFactory")
private void fooListener(ConsumerRecord<String, Foo> rec) {
    // Stuff...
}

I want to move this kafka listener into FooUtil. How can I do this? To be clear, I want FooUtil to start listening as soon as it's instantiated and initialized by a component.

Upvotes: 0

Views: 1450

Answers (2)

Fredrik Enetorp
Fredrik Enetorp

Reputation: 425

Turns out, you can make a kafka listener without using the @KafkaListener annotation (thanks Gary Russell). Just follow the instructions here (douevencode.com) for instructions of how to do it.

Upvotes: 0

Michael
Michael

Reputation: 556

Since the FooUtil is not managed by Spring you're unable to use the @KafkaListener annotation. If FooUtil was a bean managed by Spring it would be picked up by Spring and the listener annotation will cause Spring to connect the listener. All of this is done by Spring in KafkaListenerAnnotationBeanPostProcessor I believe.

Does the FooUtil have to be an unmanaged bean? I might be missing some details but from the question I can't see why it shouldn't be possible. If you need different instances for every bean using it you can use @Scope("prototype") on the FooUtil.

Upvotes: 1

Related Questions