spring-cloud / spring-cloud/spring-cloud-commons
Kotlin: variables in constructor with @ConfigurationProperties can not refresh
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 751
- Forks
- 744
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 9
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue using bootstrap.yml, the external application.yml, and POST /actuator/refresh with constructor-defined and class-body Kotlin properties. Trace the configuration refresh path and add a regression test for the constructor case; done means the changed property is actually refreshed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin, spring, spring-boot
- Domain
- backend, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100