javaspringspring-bootevent-listenerapp.yaml

Execute Spring @EventListener based on a value from application.yaml


I would like the execution of the event handler to depend on whether the property is set to true or false in application.yaml file. I have three yaml files (test, dev, prod) and I have set the settings in them:

application-dev.yml

page-cache:
  starting: false

application-test.yml

page-cache:
  starting: true

application-prod.yml

page-cache:
  starting: true

And I need not to write 'dev' or 'test' in condition myself, but to read true or false from yaml files.

For example: condition = "@serviceEnabled == true", does not work.

@Service
public class ServiceImpl {

    @Value("${page-cache.starting}")
    private Boolean serviceEnabled;

   // means that when running dev will be false and the method will not run and this code is working
    @EventListener(
        value = ApplicationReadyEvent.class,
        condition = "@environment.getActiveProfiles()[0] != 'dev'")
    public void updateCacheAfterStartup() {
        log.info("Info add starting...");
        someService.getInfo();
    }
}

I tried to do as in this article, but it doesn't work for me:

Evaluate property from properties file in Spring's @EventListener(condition = "...")

I also tried the same option

@Service
public class ServiceImpl {
    @Value("${page-cache.starting}")
    private Boolean serviceEnabled;
   
    public Boolean isServiceEnabled() {
        return this.serviceEnabled;
    }

    public Boolean getServiceEnabled() {
        return serviceEnabled;
    }

    @EventListener(
        value = ApplicationReadyEvent.class,
        condition = "@ServiceImpl.serviceEnabled")
    public void updateCacheAfterStartup() {
        log.info("Info add starting...");
        someService.getInfo();
    }
}

Solution

    1. Make sure the YAML format is correct in application-test.yml, application-prd.yml,...

      example:

      application-dev.yml

      page-cache:
         starting: false
      
    2. ServiceImpl must be a component/bean, so annotate your class with @Service, @Component or use @Bean if the instance is created in a @Configuration class.

    Extra tip:

    You could use condition = "! @environment.acceptsProfiles('dev')"

    instead of condition = "@environment.getActiveProfiles()[0] != 'dev'"

    that way the order of active profiles does not matter

    or define when the condition is valid: condition = "@environment.acceptsProfiles('test', 'prod')"

    UPDATE:

    You could also directly use page-cache.starting in the condition.

    @EventListener(
         value = ApplicationReadyEvent.class,
         condition = "@environment.getProperty('page-cache.starting')")
    public void updateCacheAfterStartup() {
        // update the cache
    }
    

    Here updateCacheAfterStartup() will only be triggered at startup when page-cache.starting is true. If set to false or when not present the method will not be called.

    If you want to force that page-cache.starting is provided (in all profiles) you should use: condition="@environment.getRequiredProperty('page-cache.starting')"