65

The Spring Boot documentation says that to use the @ConfigurationProperties annotation

You also need to list the properties classes to register in the @EnableConfigurationProperties annotation, as shown in the following example:

and gives this code:

@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}

But in the very next paragraph says:

Even if the preceding configuration creates a regular bean for AcmeProperties, we recommend that @ConfigurationProperties only deal with the environment and, in particular, does not inject other beans from the context. Having said that, the @EnableConfigurationProperties annotation is also automatically applied to your project so that any existing bean annotated with @ConfigurationProperties is configured from the Environment.

Suggesting that listing a @ConfigurationProperties bean under an @EnableConfigurationProperties annotation is not necessary.

So which is it? Experimentally, I've seen that if I annotate a bean with @ConfigurationProperties it gets properties injected to it as expected without needing to list it in @EnableConfigurationProperties, but if this is the case then why list anything that has a @ConfigurationProperties annotation under @EnableConfigurationProperties, as is shown in the documentation? Does it make any kind of difference?

M. Justin
  • 14,487
  • 7
  • 91
  • 130
J Person
  • 1,099
  • 1
  • 10
  • 15
  • check my answer here. https://stackoverflow.com/questions/48111941/spring-boot-application-test-properties/48114025#48114025 This is one example where you might usage of `@EnableConfigurationProperties` is mandatory – pvpkiran Apr 17 '18 at 14:23
  • If I understand correctly, this explains why you need `@EnableConfigurationProperties` on a configuration class, but not why you need to give it a list of classes annotated with `@Configurationproperties`, e.g. `@EnableConfigurationProperties(AcmeProperties.class)` when AcmeProperties is already annotated with `@ConfigurationProperties` – J Person Apr 17 '18 at 14:33

4 Answers4

59

As M. Deinum referred @EnableConfigurationProperties Is for enabling support of @ConfigurationProperties. If you take a look to the annotation Java Doc you can see:

Enable support for ConfigurationProperties annotated beans. ConfigurationProperties beans can be registered in the standard way (for example using Bean @Bean methods) or, for convenience, can be specified directly on this annotation. [...]

For example, let's say you have a class whose responsibility is to read and store information from your application.yml / application.properties that is required to make a connection to different databases. You annotate it with @ConfigurationProperties.

Then, you typically have a @Configuration annotated class that provides a DataSource @Bean to your application. You can use the @EnableConfigurationProperties to link it to the @ConfigurationProperties class and init your data sources accordingly.

Here is a small example:

application.yml

data-sources:
  db1:
    url: "jdbc:postgresql://localhost:5432}/db1"
    username: test
    password: test
  db2:
    url: "jdbc:postgresql://localhost:5432}/db2"
    username: test
    password: test

DataSourcesConfiguration

@ConfigurationProperties
public class DataSourcesConfiguration {

    private Map<String, BasicDataSource> dataSources;

    public void setDataSources(Map<String, BasicDataSource> dataSources) {
        this.dataSources = dataSources;
    }

    Map<String, BasicDataSource > getDataSources() {
        return dataSources;
    }
}

DataSourceConnectionConfiguration

@Configuration
@EnableConfigurationProperties(DataSourcesConfiguration.class)
public class DatabaseConnectionConfiguration implements Provider<Connection> {

    private DataSourcesConfiguration dataSourcesConfiguration;

    public DatabaseConnectionConfiguration(DataSourcesConfiguration dataSourcesConfiguration) {
        this.dataSourcesConfiguration = dataSourcesConfiguration;
    }

    @Bean
    public DataSource dataSource() {
        // Use dataSourcesConfiguration to create application data source. E.g., a AbstractRoutingDataSource..
    }

}
Ortomala Lokni
  • 56,620
  • 24
  • 188
  • 240
Emanuel Miranda
  • 887
  • 8
  • 7
  • 10
    So what difference does including DataSourcesConfiguration.class on the @EnableConfigurationProperties annotation make, compared to leaving the annotation empty? – J Person May 08 '18 at 13:22
  • 25
    The `DataSourcesConfiguration.class` is not registered as a Spring `@Bean`. Hence, if you remove the `@EnableConfigurationProperties` value, in this case `DataSourcesConfiguration.class`, Spring won't be able to find it. If you check the `@EnableConfigurationProperties::value()` docs, it says that it is just a convenient way for quickly register `@ConfigurationProperties` annotated beans. We could leave the `@EnableConfigurationProperties` empty if the `DataSourcesConfiguration` was annotated with, e.g., `@Component` annotation, which registers it as a Spring Bean. Hope this helps! – Emanuel Miranda May 09 '18 at 12:48
  • 2
    Conveniently, `@ConfigurationPropertiesScan` is meta-annotated with `@EnableConfigurationProperties`, so if you do a scan of your `config` package where you keep all the properties classes, it will also *enable* configuration properties overall. I annotated my main `@SpringBootApplication` with `@ConfigurationPropertiesScan("com.my.config")`, and the properties were finally being found as beans and getting autowired due to the scan from this one location. – George Pantazes Feb 17 '20 at 23:23
  • @EmanuelMiranda Small clarification. `DataSourcesConfiguration` doesn't register _itself_ as a bean. But eventually it is registered as a bean by the `@EnableConfigurationProperties`. So one way or another `@ConfigurationProperties` annotated class should be registered as a bean. – Ilya Serbis Sep 28 '20 at 18:44
35

It took me a while to reach to this post but would like to add here so that others may get benefited.

@ConfigurationProperties - Used to bind a class with an externalized property file. Very powerful and must be used to separate out bean classes with configuration entity class.

@Configuration - Creates a Spring bean of configuration stereotype.

@EnableConfigurationProperties - Creates a binding between a configuration entity class and Spring configuration stereotype so that after injection within a service properties can be retrieved easily.

Andy Brown
  • 11,766
  • 2
  • 42
  • 61
alpha
  • 360
  • 3
  • 4
14

If we look at the code below:

@Configuration @EnableConfigurationProperties @ConfigurationProperties(prefix="ar1") public class ar1Settings { }

  • @Configuration tells Spring to treat this as a configuration class and register it as a Bean

  • @EnableConfigurationProperties tells Spring to treat this class as a consumer of application.yml/properties values

  • @ConfigurationProperties tells Spring what section this class represents.

My understanding is that if you don't need to specify the section of the property file, then @ConfigurationProperties can be omitted.

AR1
  • 4,507
  • 4
  • 26
  • 42
  • 4
    `@EnableConfigurationProperties` is for enabling support of `@ConfigurationProperties` it should only exists once in your application (i.e on your `@SpringBootApplication` it shouldn't (nor does belong) on other classes). – M. Deinum Apr 18 '18 at 06:47
  • 1
    So what do the classes given to @EnableCOnfigurationProperties as arguments do? – J Person Apr 18 '18 at 09:22
  • @JPerson -- they indicate which `@ConfigurationProperties` Spring should enable, specifically. You'd not supply any classes if you'd like any that Spring can find to be loaded. – Josh M. Oct 18 '19 at 10:58
0

@EnableConfigurationProperties imports EnableConfigurationPropertiesRegistrar which enables support for @ConfigurationProperties annotated beans.

@ConfigurationProperties is an annotation for externalized configuration, it is to be applied to a bean configuration class or method annotated with @Bean eg

   @ConfigurationProperties(prefix = "some-prefix")
   public SomePrefix prefixBean() { 
      return new SomePrefix(); 
}

To load the properties and bind them to properties within the method or the class that match the prefix. ps: some-prefix binds to SomePrefix because of spring's support for Relaxed binding.

Before springboot 2.2, You could do either of the following:

@Configuration
@ConfigurationProperties(prefix = "some-prefix")
public class ConfigProperties {
//...some code
}

or

@Configuration
@EnableConfigurationProperties(SomeClassToBeBounded.class)
public class ConfigProperties {

along with

@ConfigurationProperties(prefix = "some-prefix")
public class SomeClassToBeBounded{
//...some code
}

From springboot 2.2

You can do it in a much easier way:

@ConfigurationProperties(prefix = "some-prefix") 
@ConfigurationPropertiesScan 
public class ConfigProperties { 

//...some code
}

With this, the classpath scanner enabled by @SpringBootApplication finds the ConfigProperties class, even though we didn't annotate this class with @Component.

Amos Kosgei
  • 877
  • 8
  • 14