ttulka
ttulka

Reputation: 10892

Spring Boot doesn't load a Map from environment variables when in camel-case

I set environment variables

MY_APP_MY_MAP_A1=a
MY_APP_MY_MAP_A2=b
MY_APP_JUSTMAP_A1=a
MY_APP_JUSTMAP_A2=b

to configure my Spring Boot (2.1.7.RELEASE) application via @ConfigurationProperties:

@SpringBootApplication
@EnableConfigurationProperties(MyApp.MyProperties.class)
public class MyApp {

    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }

    @Bean
    public CommandLineRunner cmd(MyProperties props) {
        return args -> {
            System.out.println("myMap: " + props.getMyMap());
            System.out.println("justmap: " + props.getJustmap());
        };
    }

    @ConfigurationProperties(prefix = "my.app")
    @Getter
    @Setter
    static class MyProperties {
        private Map<String, String> myMap;
        private Map<String, String> justmap;
    }
}

Setting a Map<String,String> doesn't work when the variable name contains an upper letter (is in camelcase), otherwise everything works fine:

myMap: null
justmap: {a1=a, a2=b}

Is there a way how to do it?

Upvotes: 5

Views: 2471

Answers (2)

wheleph
wheleph

Reputation: 8354

Elaborating on the Shailendra's answer here's a relevant quote from docs:

To convert a property name in the canonical-form to an environment variable name you can follow these rules:

  • Replace dots (.) with underscores (_).
  • Remove any dashes (-).
  • Convert to uppercase.

Upvotes: 0

Shailendra
Shailendra

Reputation: 9102

If you have following env. variables passed

MY_APP_MYMAP_A1=a
MY_APP_MYMAP_A2=b
MY_APP_JUSTMAP_A1=a
MY_APP_JUSTMAP_A2=b

The below code prints what you are expecting

@SpringBootApplication
@EnableConfigurationProperties(TestSpringBootApplication.MyProperties.class)
public class TestSpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestSpringBootApplication.class, args);
    }

    @Bean
    public CommandLineRunner cmd(MyProperties props) {
        return args -> {
            System.out.println("myMap: " + props.getMyMap());
            System.out.println("justmap: " + props.getJustmap());
        };
    }

    @ConfigurationProperties(prefix = "my.app")   
    static class MyProperties {
        private Map<String, String> myMap;
        private Map<String, String> justmap;

        public Map<String, String> getMyMap() {
            return myMap;
        }
        public void setMyMap(Map<String, String> myMap) {
            this.myMap = myMap;
        }
        public Map<String, String> getJustmap() {
            return justmap;
        }
        public void setJustmap(Map<String, String> justmap) {
            this.justmap = justmap;
        }

    }

}

The output is below

2019-09-04 16:00:07.336  INFO 21204 --- [           main] c.e.demo.TestSpringBootApplication       : Started TestSpringBootApplication in 1.012 seconds (JVM running for 2.219)
myMap: {a1=a, a2=b}
justmap: {a1=a, a2=b}

For more details on the rules around this relaxed binding check the documentation here

Upvotes: 6

Related Questions