Search code examples
javaspring-bootspring-annotations

Can't bind properties with @Bean and @ConfigurationProperties


I am reading configuration from properties file. Now I am having an error that I think is related to sequence of initialization of spring bean.

If I do private Map name = new HashMap<>(); It can be successfully load from properties file.

But now I am having Could not bind properties to ServiceNameConfig

I don't know why this happen and how to deal with it.

@ConfigurationProperties(prefix = "amazon.service")
@Configuration
@EnableConfigurationProperties(ServiceNameConfig.class)
public class ServiceNameConfig {

   //If I do private Map<String, String> name = new HashMap<>(); It can be successfully load from properties file.
    private Map<String, String> name;

    @Bean(value = "serviceName")
    public Map<String, String> getName() {
        return name;
    }

    public void setName(Map<String, String> name) {
        this.name = name;
    }

} 

its usage;

@Autowired
@Qualifier("serviceName")
Map<String, String> serviceNameMap;

Solution

  • You can replace your config class to be like this (simpler);

    @Configuration
    public class Config {
    
        @Bean
        @ConfigurationProperties(prefix = "amazon.service")
        public Map<String, String> serviceName() {
            return new HashMap<>();
        }
    }
    

    For @ConfigurationProperties injection, you'd need to supply an empty instance of the bean object. Check more about it on baeldung


    Or an alternative way, you can use a pojo class to handle the configuration. For example;

    You have properties like;

    amazon:
      service:
        valueA: 1
        valueB: 2
        details:
          valueC: 3
          valueD: 10
    

    and you can use a pojo like the following;

    class Pojo {
    
        private Integer valueA;
        private Integer valueB;
        private Pojo2 details;
    
        // getter,setters
    
        public static class Pojo2 {
    
            private Integer valueC;
            private Integer valueD;
    
            // getter,setters
        }
    }
    

    and use it in the config class like;

    @Configuration
    public class Config {
    
        @Bean
        @ConfigurationProperties(prefix = "amazon.service")
        public Pojo serviceName() {
            return new Pojo();
        }
    }