Kotlin & Spring Boot @ConfigurationProperties
How to properly initialize ConfigurationProperties in Spring Boot with Kotlin?
Currently I do like in the example below:
@ConfigurationProperties("app")
class Config {
var foo: String? = null
}
But it looks pretty ugly and actually foo
is not a var
iable, foo is constant val
ue and should be initialized during startup and will not change in the future.
Solution 1:
With new Spring Boot 2.2 you can do like so:
@ConstructorBinding
@ConfigurationProperties(prefix = "swagger")
data class SwaggerProp(
val title: String, val description: String, val version: String
)
And don't forget to include this in your dependencies in build.gradle.kts
:
dependencies {
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
}
Solution 2:
Here is how I have it working with my application.yml file.
myconfig:
my-host: ssl://example.com
my-port: 23894
my-user: user
my-pass: pass
Here is the kotlin file:
@Configuration
@ConfigurationProperties(prefix = "myconfig")
class MqttProperties {
lateinit var myHost: String
lateinit var myPort: String
lateinit var myUser: String
lateinit var myPass: String
}
This worked great for me.
Solution 3:
Update: As of Spring Boot 2.2.0, you can use data classes as follows:
@ConstructorBinding
@ConfigurationProperties("example.kotlin")
data class KotlinExampleProperties(
val name: String,
val description: String,
val myService: MyService) {
data class MyService(
val apiToken: String,
val uri: URI
)
}
For further reference, see the official documentation.
Obsolete as of Spring Boot 2.2.0, Issue closed
As stated in the docs: A "Java Bean“ has to be provided in order to use ConfigurationProperties
. This means your properties need to have getters and setters, thus val
is not possible at the moment.
Getters and setters are usually mandatory, since binding is via standard Java Beans property descriptors, just like in Spring MVC. There are cases where a setter may be omitted [...]
This has been resolved for Spring Boot 2.2.0, which is supposed to be released soon: https://github.com/spring-projects/spring-boot/issues/8762
Solution 4:
On Spring Boot 2.4.3 with Kotlin 1.4.3 the next approach is no longer working (maybe because of a bug):
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.EnableConfigurationProperties
@SpringBootApplication
@EnableConfigurationProperties(TestProperties::class)
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConstructorBinding
@ConfigurationProperties(prefix = "test")
@ConstructorBinding
data class TestProperties(
val value: String
)
The code above starts working after implying one of the next two approaches:
- Add dependency
implementation("org.jetbrains.kotlin:kotlin-reflect")
- Update Properties class
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConstructorBinding
@ConfigurationProperties(prefix = "test")
data class TestProperties @ConstructorBinding constructor(
val value: String
)
The problem happens at the line org/springframework/boot/context/properties/ConfigurationPropertiesBindConstructorProvider.java#68