1. Overview
In this article, we will learn to implement the Spring ConfigurationProperties using Kotlin data class.
2. Kotlin data class for ConfigurationProperties
Consider that the application property file contains the following properties.
server.error.path=/error server.port=9000
You can bind the above properties to Kotlin fields by annotating the class using the @ConfigurationProperties
. Note that the @ConfigurationProperties
support properties that are hierarchical.
For example, the server.error.path
is hierarchical and nested property i.e., the root server
prefix property contains the error
nested property. The @ConfigurationProperties
support multiple prefixes that have the same root prefix like below:
@Component @ConfigurationProperties(value = "server") data class AppProperties(var address: String?, var error: Error) @Component data class Error(var path: String?)
@SpringBootApplication open class ConfigurationPropertiesApplication : CommandLineRunner { @Autowired lateinit var appProperties : AppProperties private val logger: Logger = LoggerFactory.getLogger(ConfigurationPropertiesApplication::class.java) override fun run(vararg args: String?) { logger.info(appProperties.address) logger.info(appProperties.error.path) } } fun main(args: Array<String>) { runApplication<ConfigurationPropertiesApplication>(*args) }
3.1. Kotlin data class @ConstructorBinding
Alternatively, you can use @ConstructorBinding
if your project uses the Spring Boot framework version 2.2.0.RELEASE
or above.
This annotation supports binding the configuration properties to constructor arguments rather than by calling setters.
You cannot use the Constructor binding with beans that are created by the regular Spring mechanisms (e.g. @Component
beans, beans created via @Bean
methods, or beans loaded using @Import
).
However, you can use @EnableConfigurationProperties
to enable configuration properties scanning and register the class as a Spring bean. To understand this registration concept, refer to the next section.
@ConstructorBinding @ConfigurationProperties(value = "server") data class AppProperties(val address: String?, val error: Error) @Component data class Error(var path: String?)
4. Register Spring @ConfigurationProperties in a standard way
You can register the @ConfigurationProperties
beans in the standard way (for example using @Bean
methods, using @Component
or @Configuration
annotations). You can refer to this article to understand bean instantiation.
For example, the following AppProperties
class is annotated with @Component
, so the Spring container detects this bean during component scanning and then instantiates, and registers it as a bean.
As discussed in the previous section, this only works when the @ConfigurationProperty
not annotated with @ConstructorBinding
.
@Component @ConfigurationProperties(value = "server") data class AppProperties(var address: String?, var error: Error) @Component data class Error(var path: String?)
You can access the fields or properties of this bean later in your application.
For example, we have auto wired the appProperties
bean and accessing it just like any other Spring bean.
@SpringBootApplication open class ConfigurationPropertiesApplication : CommandLineRunner { @Autowired lateinit var appProperties : AppProperties private val logger: Logger = LoggerFactory.getLogger(ConfigurationPropertiesApplication::class.java) override fun run(vararg args: String?) { logger.info(appProperties.address) logger.info(appProperties.error.path) } } fun main(args: Array<String>) { runApplication<ConfigurationPropertiesApplication>(*args) }
However, if you remove the annotation @Component
, then the following error appears on the application start-up.
Field appProperties in com.tedblob.profiles.ProfilesApplication required a bean of type 'com.tedblob.profiles.configurations.AppProperties' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) Action: Consider defining a bean of type 'com.tedblob.profiles.configurations.AppProperties' in your configuration.
5. Register using the @EnableConfigurationProperties
Alternatively, you can also use this @EnableConfigurationProperties
annotation to support the @ConfigurationProperties
for convenience.
For example, the @EnableConfigurationProperties
takes the list of @ConfigurationProperty
classes as input and allows the Spring container to detect and manage them as regular Spring beans.
@SpringBootApplication @EnableConfigurationProperties(AppProperties::class) open class ConfigurationPropertiesApplication : CommandLineRunner { @Autowired lateinit var appProperties : AppProperties private val logger: Logger = LoggerFactory.getLogger(ConfigurationPropertiesApplication::class.java) override fun run(vararg args: String?) { logger.info(appProperties.address) logger.info(appProperties.error.path) } }
6. Conclusion
To sum up, we have learned to implement the Spring ConfigurationProperties using the Kotlin data class.