Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConfigurationProperties loading list from YML

I'm trying to load Configuration from YML. I can load value and I can also load list if these are comma seperated values. But i can't load a typical YML List.

Configuration Class

@Component
@PropertySource("classpath:routing.yml")
@ConfigurationProperties
class RoutingProperties(){
    var angular = listOf("nothing")
    var value: String = ""
}

Working routing.yml

angular: /init, /home
value: Hello World

Not Working routing.yml

angular:
    - init
    - home

value: Hello World

Why can't i load the second version of yml / do I have a syntaxt error?

ENV: Kotlin, Spring 2.0.0.M3

like image 841
robie2011 Avatar asked Aug 25 '17 11:08

robie2011


2 Answers

As @flyx say, @PropetySource not worked with yaml files. But in spring you may override almost everything :)

PropertySource has additional parameter: factory. It's possible to create your own PropertySourceFactory base on DefaultPropertySourceFactory

open class YamlPropertyLoaderFactory : DefaultPropertySourceFactory() {
    override fun createPropertySource(name: String?, resource: EncodedResource?): org.springframework.core.env.PropertySource<*> {
        if (resource == null)
            return super.createPropertySource(name, resource)

        return YamlPropertySourceLoader().load(resource.resource.filename, resource.resource, null)
    }
}

And when use this factory in propertysource annotation:

@PropertySource("classpath:/routing.yml", factory = YamlPropertyLoaderFactory::class)

Last that you need is to initialized variable angular with mutableList

Full code sample:

@Component
@PropertySource("classpath:/routing.yml", factory = YamlPropertyLoaderFactory::class)
@ConfigurationProperties
open class RoutingProperties {
    var angular = mutableListOf("nothing")
    var value: String = ""


    override fun toString(): String {
        return "RoutingProperties(angular=$angular, value='$value')"
    }
}

open class YamlPropertyLoaderFactory : DefaultPropertySourceFactory() {
    override fun createPropertySource(name: String?, resource: EncodedResource?): org.springframework.core.env.PropertySource<*> {
        if (resource == null)
            return super.createPropertySource(name, resource)

        return YamlPropertySourceLoader().load(resource.resource.filename, resource.resource, null)
    }
}

@SpringBootApplication
@EnableAutoConfiguration(exclude = arrayOf(DataSourceAutoConfiguration::class))
open class Application {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val context = SpringApplication.run(Application::class.java, *args)

            val bean = context.getBean(RoutingProperties::class.java)

            println(bean)
        }
    }
} 
like image 106
kurt Avatar answered Nov 07 '22 19:11

kurt


Kinda old post, i know. But i am at the very same topic right now.

As of now, it seems that PropertySource does indeed work with yaml Files. Given the restriction that it only allows for primitive types (it seems) and it cant handle nested elements. I'm probably gonna dig a bit deeper and update my answer accordingly, but as of now, the accepted answer seems like a functioning workaround.

like image 38
glace Avatar answered Nov 07 '22 20:11

glace