Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin Spring boot @ConfigurationProperties for list

I want to read the yaml config files using Kotlin and below is my code: application.yml

message:
  messages:
    - name: abc
      type: aaa
      size: 10
    - name: xyz
      type: bbb
      size: 20

MessageConfig.kt

package com.example.demokotlin

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration
import java.math.BigDecimal

@ConfigurationProperties(prefix = "message")
@Configuration
class MessageConfig {
  lateinit var messages: List<Message>
}

class Message {
  lateinit var name: String
  lateinit var type: String
  lateinit var size: BigDecimal
}

Class to use the config:

package com.example.demokotlin

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

@Component
class MessageService @Autowired constructor(private var messageConfig: MessageConfig) {

  fun createMessage(): String {
    println("in service........")
    println(messageConfig.messages[0].name)
    println(messageConfig.messages[0].type)
    println(messageConfig.messages[0].size)
    return "create a message......."
  }
}

Looks like if the yaml file has array/list, Kotlin can't read it properly but it works without array.

I have exactly the same code and works for Java. Something wrong with my Kotlin code?

like image 271
ttt Avatar asked Jan 18 '18 16:01

ttt


Video Answer


2 Answers

You are encountering this bug. Simply changing

lateinit var messages: List<Message>

to

var messages: MutableList<Message> = mutableListOf()

makes your code work. Here is a full working example.

edit (March 2019):

As of SB 2.0.0.RC1 and Kotlin 1.2.20, you can use lateinit or a nullable var.

Docs

edit (May 2020):

As of SB 2.2.0 you can use @ConstructorBinding along with @ConfigurationProperties to set val properties on a data class.

Using the original class as an example, you can now write it like so:

@ConstructorBinding
@ConfigurationProperties(prefix = "message")
data class MessageConfig(val messages: List<Message>) {
  data class Message(
    val name: String,
    val type: String,
    val size: BigDecimal
  )
}
like image 132
snowe Avatar answered Sep 23 '22 14:09

snowe


Is Fixed in Kotlin 1.3.11 with spring-boot 2.10, sample provided in MessageConfig.kt works now

@PropertySource("classpath:application.yml")
@ConfigurationProperties(value = "message")
class MessageConfig {
  lateinit var messages: List<Message>
}

class Message {
  lateinit var name: String
  lateinit var type: String
  lateinit var size: BigDecimal
}
like image 35
Pieter van der Meer Avatar answered Sep 24 '22 14:09

Pieter van der Meer