spring-cloud-commons
spring-cloud-commons copied to clipboard
Kotlin: variables in constructor with @ConfigurationProperties can not refresh
Moved from spring-cloud-kubernetes.
I found a similar issue #823. Finally the author said:
You were right. The issue was with Kotlin Data class which is immutable in nature. Changing this to something like this
@ConfigurationProperties(prefix = "myapp") @ConstructorBinding class MyApConfig { lateinit var name: String lateinit var message: String }
works.
I don't agree with this view. Data class is not completely immutable, you can make it mutable by var
. After further testing, I found that it had nothing to do with data class. The key lies in the position of the variable definition. If the variable is defined in the constructor, it is not refreshed, although it is mutable (var
).
// won't refresh
@ConstructorBinding
@ConfigurationProperties(prefix = "bean")
class TestProps(
var message: String
)
// will refresh
@ConstructorBinding
@ConfigurationProperties(prefix = "bean")
class TestProps {
lateinit var message: String
}
The only difference between the two style is whether delay initialization is allowed. Maybe that's the cause. But I don't know the exact principle of refresh and there's no log. Hope someone can investigate further.
Reproduction step
- Spring Boot: 2.4.8
- Spring Cloud: 2020.0.4
Dependencies:
implementation("org.springframework.cloud:spring-cloud-commons")
implementation("org.springframework.cloud:spring-cloud-starter-bootstrap")
implementation("org.springframework.cloud:spring-cloud-starter-config")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
bootstrap.yml:
spring:
config:
import: file:/path/to/application.yml
- Start the app.
- Change
/path/to/application.yml
. - POST
/actuator/refresh
, got["bean.message"]
(should refresh successfully) - Confirm that there is no actual refresh.
I've spotted the same issue and completely agree with author. At least adding some DEBUG log could be useful to point out that refresh cannot be done.
This is still an issue in Spring Cloud 2023.0.0-M2 and Spring Boot 3.2.0-M3:
// this refreshes
@ConfigurationProperties("app.props")
class AppProps {
var text: String = ""
var number: Int = 0
var list: List<String> = listOf()
}
// this does not
@ConfigurationProperties("app.props2")
data class AppProps2(
var text: String,
var number: Int,
var list: List<String>
)