5

I have this custom object:

data class Pair(
        var first: String = "1",
        var second: String = "2"
)

And now I want to autowire it with my application.yml:

my-properties:
my-integer-list:
  - 1
  - 2
  - 3
my-map:
  - "abc": "123"
  - "test": "test"
pair:
  first: "abc"
  second: "123"

Using this class:

@Configuration
@ConfigurationProperties(prefix = "my-properties")
class ComplexProperties {
    lateinit var myIntegerList: List<Int>
    lateinit var myMap: Map<String, String>
    lateinit var pair: Pair
}

Before adding Pair it worked ok, but after I only get Reason: lateinit property pair has not been initialized

This is my main:

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

@RestController
class MyRestController(
        val props: ComplexProperties
) {
    @GetMapping
    fun getProperties(): String {

        println("myIntegerList: ${props.myIntegerList}")
        println("myMap: ${props.myMap}")
        println("pair: ${props.pair}")

        return "hello world"
    }
}

With java I already accomplished this, but I can't see what's missing here.

rado
  • 5,720
  • 5
  • 29
  • 51
  • Why are you writing your own `Pair` when Kotlin has one already? And why use ambiguous names `first` and `second` for configuration? I think this question suffers from the [XY Problem](http://xyproblem.info/) – ordonezalex Jul 22 '19 at 19:48
  • Well, because with Kotlin's `Pair` I had the same error. So I tried to create one on my own. But it presented the same behavior. I just copied from original `Pair`. Do you have any working case with this condition, using Kotlin's `Pair`? – rado Jul 22 '19 at 20:05

2 Answers2

5

You can't do that with a lateinit var.

The solution is to either init your pair property to null:

@Configuration
@ConfigurationProperties(prefix = "my-properties")
class ComplexProperties {
    ...
    var pair: Pair? = null
}

Or instantiate your pair with default values:

@Configuration
@ConfigurationProperties(prefix = "my-properties")
class ComplexProperties {
    ...
    var pair = Pair()
}

You can now autowire it with your application.yml:

...
pair:
  first: "abc"
  second: "123"
vSomers
  • 426
  • 3
  • 13
1

Another possible solution is to use @ConstructionBinding annotation. It will initialize property using constructor so there is no need for nullability of default value.

@ConstructorBinding
@ConfigurationProperties("my-properties")
class ComplexProperties (
    val pair: Pair
)
mixnix
  • 455
  • 3
  • 13