Scenario:
A ConfigurationProperties class contains a Map<String, String> property.
The contents of the map are specified in an application.yml file.
Expected behavior: The order of the map entries (as specified in the yaml file) is preserved. This is the case with Spring-Boot 2.2.7.
Actual behavior: The order of the map entries (as specified in the yaml file) is not preserved. This is the case with Spring-Boot 2.3.0.
Minimal project to reproduce:
DemoApplication.kt:
package com.example.demo
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.boot.context.properties.ConstructorBinding
import org.springframework.boot.runApplication
import javax.annotation.PostConstruct
@ConfigurationProperties("test")
@ConstructorBinding
class Properties(
val map: Map<String, String>
)
@SpringBootApplication
@ConfigurationPropertiesScan
class DemoApplication {
@Autowired
private lateinit var properties: Properties
@PostConstruct
fun postInit() {
println(properties.map.toString())
}
}
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
application.yml:
test:
map:
foo: foo
baz: baz
bar: bar
Spring-Boot 2.2.7 prints: {foo=foo, baz=baz, bar=bar}
Spring-Boot 2.3.0 prints: {baz=baz, bar=bar, foo=foo}
Demo Project: demo.zip
Comment From: wilkinsona
Thanks for the report. I'm not sure that we've ever deliberately guaranteed the ordering, but I can see that it's changed in 2.3. I get {foo=foo, baz=baz, bar=bar} with RC1 (the same as 2.2.7) so, whatever the cause, it's recent.
Comment From: elitacco
This issue breaks spring cloud zuul routes configuration.
From Spring Clould Netflix documentation:
If you need your routes to have their order preserved, you need to use a YAML file, as the ordering is lost when using a properties file. The following example shows such a YAML file:
yaml zuul: routes: users: path: /myusers/** legacy: path: /*
If you were to use a properties file, the legacy path might end up in front of the users path, rendering the users path unreachable.
Comment From: dumitrulapteacru-endava
Is somewhere documented that order is preserved?
Comment From: wilkinsona
@dumitrulapteacru-endava No, I don't believe so. As I said above we've never deliberately guaranteed the ordering. I would avoid relying on it unless you have a good reason to do so.
Comment From: dumitrulapteacru-endava
thank you @wilkinsona