admin管理员组

文章数量:1410737

I have a spring boot - kotlin project, which I am upgrading from Spring 5, Java 8 to Spring 6, Java 21

build.gradle.kts

plugins {
    kotlin("jvm") version "2.1.20"
    id(".springframework.boot") version "3.4.4"
    id(".jetbrains.kotlin.plugin.spring") version "2.1.20"
    id("io.spring.dependency-management") version "1.1.7"
}

dependencies {
    implementation(".springframework.boot:spring-boot-starter")
    implementation(kotlin("reflect"))
}

MyProperties.kt

@ConfigurationProperties(prefix = "my.test")
@Component
class MyProperties {
    var customs: List<CustomA> = listOf()
    var bases: List<Base> = listOf()

    open class Base(
        var type: String = ""
    )

    class CustomA(
        var y: String = "",
        var z: String = "",
    ) : Base()
}

Run the application by bootRun task, with these env variables:

MY_TEST_BASES_0_TYPE=value4;MY_TEST_CUSTOMS_0_TYPE=value3;MY_TEST_CUSTOMS_0_Y=value1;MY_TEST_CUSTOMS_0_Z=value2

I would expect that the myProperties.customs[0].type would return value3, but it would return an empty string instead.

The problem only happens if the kotlin("reflect") dependency exists and does not occur in Spring 5, java 8.

It looks like the base class's properties are not bound at all. If I modify the MyProperties class as this, the type property will bind correctly

open class Base(
   open var type: String = ""
)

class CustomA(
   override var type: String = "",
   var y: String = "",
   var z: String = "",
) : Base()

Questions: Are there any fixes for all classes? In my code base, I have multiple Kotlin classes that extend from another base Kotlin class so manually fixing each class would not be a good idea.

I have a spring boot - kotlin project, which I am upgrading from Spring 5, Java 8 to Spring 6, Java 21

build.gradle.kts

plugins {
    kotlin("jvm") version "2.1.20"
    id(".springframework.boot") version "3.4.4"
    id(".jetbrains.kotlin.plugin.spring") version "2.1.20"
    id("io.spring.dependency-management") version "1.1.7"
}

dependencies {
    implementation(".springframework.boot:spring-boot-starter")
    implementation(kotlin("reflect"))
}

MyProperties.kt

@ConfigurationProperties(prefix = "my.test")
@Component
class MyProperties {
    var customs: List<CustomA> = listOf()
    var bases: List<Base> = listOf()

    open class Base(
        var type: String = ""
    )

    class CustomA(
        var y: String = "",
        var z: String = "",
    ) : Base()
}

Run the application by bootRun task, with these env variables:

MY_TEST_BASES_0_TYPE=value4;MY_TEST_CUSTOMS_0_TYPE=value3;MY_TEST_CUSTOMS_0_Y=value1;MY_TEST_CUSTOMS_0_Z=value2

I would expect that the myProperties.customs[0].type would return value3, but it would return an empty string instead.

The problem only happens if the kotlin("reflect") dependency exists and does not occur in Spring 5, java 8.

It looks like the base class's properties are not bound at all. If I modify the MyProperties class as this, the type property will bind correctly

open class Base(
   open var type: String = ""
)

class CustomA(
   override var type: String = "",
   var y: String = "",
   var z: String = "",
) : Base()

Questions: Are there any fixes for all classes? In my code base, I have multiple Kotlin classes that extend from another base Kotlin class so manually fixing each class would not be a good idea.

Share Improve this question edited Mar 23 at 9:59 minh tri Vo asked Mar 23 at 9:36 minh tri Vominh tri Vo 6046 silver badges13 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Confirmed as spring boot bug in https://github/spring-projects/spring-boot/issues/44849

Sadly, no fix can applied to all classes, but to minimize the changes, we can either:

a. Use @Autowired to make constructor not used for property binding:

class CustomA @Autowired constructor(
    var y: String = "",
    var z: String = "",
) : Base()

b. Declare subclass with only default constructor

class CustomA : Base() {
    var y: String = ""
    var z: String = ""
}

本文标签: