7

I need to read all properties in application.properties file in a map In the code below the property test has the respective value but the map is empty. How can I fill "map" with the values in the application.properties file without adding a prefix to the properties.

This is my application.properties file

AAPL=25
GDDY=65
test=22

I'm using @ConfigurationProperties like this

@Configuration
@ConfigurationProperties("")
@PropertySource("classpath:application.properties")
public class InitialConfiguration {
    private HashMap<String, BigInteger> map = new HashMap<>();
    private String test;

    public HashMap<String, BigInteger> getMap() {
        return map;
    }

    public void setMap(HashMap<String, BigInteger> map) {
        this.map = map;
    }

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }
}
Jorge Miralles
  • 73
  • 1
  • 1
  • 3

5 Answers5

4

You can't do it with @ConfigurationProperties as far as I'm aware, those require a prefix to be able to load those properties within the bean.

However, if your goal is to obtain "value Y" for "property X" programmatically, you can always inject Environment and use the getProperty() method to find certain property, for example:

@Configuration
public class InitialConfiguration {
    @Autowired
    private Environment environment;

    @PostConstruct
    public void test() {
        Integer aapl = environment.getProperty("AAPL", Integer.class); // 25
        Integer gddy = environment.getProperty("GDDY", Integer.class); // 65
        Integer test = environment.getProperty("test", Integer.class); // 22
    }
}
g00glen00b
  • 41,995
  • 13
  • 95
  • 133
  • Thanks I tried this but din't want to use the Enviroment directly, but this is the simplest solution – Jorge Miralles Sep 10 '18 at 15:38
  • This should be the selected answer. Loading through environment is the most robust way. – Amit Goldstein Dec 23 '20 at 14:09
  • PropertiesLoaderUtils will load properties in build time. If we change the properties at a later time and re-run the JAR, PropertiesLoaderUtils will not reflect the new changes. In that regards Environment is the best way to do it. – skaveesh Sep 10 '21 at 08:00
4

This can be achieved using the PropertiesLoaderUtils and @PostConstruct

Please check the sample below:

@Configuration
public class HelloConfiguration {
    private Map<String, String> valueMap = new HashMap<>();
    @PostConstruct
    public void doInit() throws IOException {
        Properties properties = PropertiesLoaderUtils.loadAllProperties("application.properties");
        properties.keySet().forEach(key -> {
            valueMap.put((String) key, properties.getProperty((String) key));
        });
        System.err.println("valueMap -> "+valueMap);
    }
    public Map<String, String> getValueMap() {
        return valueMap;
    }
    public void setValueMap(Map<String, String> valueMap) {
        this.valueMap = valueMap;
    }
}
Saikat
  • 548
  • 1
  • 4
  • 12
2

In spring boot, if you need to get a single value from the application.proprties, you just need to use the @Value annotation with the given name

So to get AAPL value just add a class level property like this

@Value("${AAPL}")
private String aapl;

And if you need to load a full properties file as a map, I'm using the ResourceLoader to load the full file as a stream and then parse it as follows

@Autowired
public loadResources(ResourceLoader resourceLoader) throws Exception {      
      Resource resource = resourceLoader.getResource("classpath:myProperties.properties"));
      BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
      String line;
      int pos = 0;
      Map<String, String> map = new HashMap<>();
      while ((line = br.readLine()) != null) {
           pos = line.indexOf("=");
           map.put(line.substring(0, pos), line.substring( pos + 1));
      }
}
Hany Sakr
  • 2,591
  • 28
  • 27
1

Indeed you can use @ConfigurationProperties without prefix to get entire properties known to Spring application i.e. application, system and environment properties etc.

Following example creates a fully populated map as a Spring bean. Then wire / inject this bean wherever you need it.

@Configuration
class YetAnotherConfiguration {

    @ConfigurationProperties /* or @ConfigurationProperties("") */
    @Bean
    Map<String, String> allProperties() {
        return new LinkedHashMap<>();
    }

}

@Autowire
void test(Map<String, String> allProperties) {
    System.out.println(allProperties.get("AAPL")); // 25
    ...
}
bjmi
  • 497
  • 3
  • 12
  • Newer versions of Spring Boot now require that the `@ConfigurationProperties(prefix = "non-empty")` annotation has a mandatory `prefix` parameter. – MarkHu May 10 '22 at 18:24
  • Indeed IntelliJ complains with "Prefix must be specified" or "Prefix must be non-empty" but there is no restriction mentioned in documentation of [ConfigurationProperties](https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationProperties.java). I looks like an inspection bug there. - [IDEA-219436](https://youtrack.jetbrains.com/issue/IDEA-219436) – bjmi May 11 '22 at 13:42
0
@PropertySource("classpath:config.properties")
public class GlobalConfig {

  public static String AAPL;
  @Value("${AAPL}")
  private void setDatabaseUrl(String value) {
    AAPL = value;
  }
}

You have to use @Value to get value from application.properties file

Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • This doesn't answer the OP question, which wanted to dynamically get a list of all properties. – MarkHu May 10 '22 at 17:56