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