1

I am having Kafka Listener which I want to enable or disable based on Value from DB. I am using @Conditional annotation in which I am trying to get value from the Database through CrudRepository. here is the code:

Listener class:

@Service
@Conditional(MyCondition.class)
public class TestKafkaListenerClass {

@KafkaListener(topicPattern = “(TestPattern)”, groupId = “TestGroupID”, containerFactory = “TestContainerFactory")
    public void TestListener(String Event, Acknowledgment acknowledgment){

    //proccesing event
}

MyCondition.class

 public class MyCondition implements Condition{

@Autowired
TestRepository testRepository;

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

    System.out.println("test repository value >>>"+testRepository); 
    // getting null value for testRepository 
  
return testRepository.getValueFromDb();

}

}

with hardcoded values in the matches method, everything is working as expected but when trying to get value from testRepository it's throwing a null pointer exception

but the same testRepository is working fine in another place in the application.

how to resolve this, or is there any better way to achieve the same? Thanks!

Rahul_Mandhane
  • 187
  • 1
  • 11

1 Answers1

0

I don't think you can do this just by calling the repository: The @Conditional-s are resolved during the spring application startup process. This process creates the bean definitions from what has been resolved to be loaded and only then loads actual beans, including those of spring data. So in other words, calling spring data "regular" beans should be done only when the application is started up and running.

You can try the following approaches instead:

  1. Call the database completely bypassing spring infrastructure from your conditional. This is kind of bad thing because you might end up with unclosed connections, and also the issue of credentials resolution might arise (these are probably also managed by spring boot)
  2. Don't start the Kafka Listener automatically. Customize the AbstractKafkaListenerContainerFactory (see this SO question) Then create a listener that will trigger when the application is ready with @EventListener annotation that reacts to ApplicationReadyEvent By the time this listener is triggered by spring boot, all the beans are loads (including the spring data repositories), basically that's the last step before the application is up and running. In this listener call the database and depending on the result, start or don't start the kafka listener programmatically

This is slightly different from what you've asked (the bean of listener is still loaded, but the listener is still not active when needed). By Far that's the best solution I can come up with if you only have spring boot to solve this issue.

  1. You can create an external script that will call the database (or maybe you have a configuration system or something) and will map this property to some boolean "business friendly name". Then supply this parameter to your spring boot application and base the conditional on the value found in this parameter. You can use @ConditionalOnProperty on the kafka listener for example.
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97