4

I read through the Spring Boot documentation for externalized configuration and I see that it automatically loads the src/main/resources/application.properties file which can be then wired to the bean properties using annotation.

However I want to have a generic PropertyHelper class which can be used to build the java.util.Properties with the properties in application.properties. Can this be done?

We are currently achieving this manually as below:

public class PropertyHelper { private static Properties loadProperties() { try { String propsName = "application.properties"; InputStream propsStream = PropertyHelper.class .getClassLoader().getResourceAsStream(propsName); if (propsStream == null) { throw new IOException("Could not read config properties"); } Properties props = new Properties(); props.load(propsStream); 
7
  • add a slash before application.properties Commented Sep 19, 2016 at 5:32
  • 3
    Or you can just autowire Environment which is a Properties-type bean containing all values from the file Commented Sep 19, 2016 at 5:40
  • 1
    With Environment you can get the properties, but it doesn't have a list of all properties. you only can use env.getProperty("propertyName") to get the property Commented Sep 19, 2016 at 5:44
  • For Can this be done ? , what is the result of your experiment? Commented Sep 19, 2016 at 5:51
  • However, the Environment is very likely a ConfigurableEnvironment, which allows you to iterate the property sources, and you can iterate the properties of any PropertySource that is an EnumerablePropertySource. --- The advantage of using Environment is that you gain support for features like Profiles and YAML. But the question is: Why do you need to iterate them? Don't you know the names of the properties that are of interest to you? Commented Sep 19, 2016 at 5:52

3 Answers 3

1

You could create a Wrapper around Environment, which would return a ready-to-use PropertySource:

You would use it this way:

@PropertySource(name="myName", value="classpath:/myName.properties") public class YourService { @Autowired private CustomMapProperties customMapProperties; ... MapPropertySource mapPropertySource = customMapProperties.getMapProperties("myName"); for(String key: mapPropertySource.getSource().keySet()){ System.out.println(mapPropertySource.getProperty(key)); } 

CustomMapProperties is injected with Environment and returns the request & loaded property file based on its name:

@Component public class CustomMapProperties { @Autowired private Environment env; public MapPropertySource getMapProperties(String name) { for (Iterator<?> it = ((AbstractEnvironment) env).getPropertySources().iterator(); it.hasNext();) { Object propertySource = it.next(); if (propertySource instanceof MapPropertySource && ((MapPropertySource) propertySource).getName().equals(name)) { return (MapPropertySource) propertySource; } } return null; } } 
Sign up to request clarification or add additional context in comments.

Comments

0

Here is how I derive a Properties object from Spring's Environment. I look for property sources of type java.util.Properties, which in my case will give me system properties and application properties.

@Resource private Environment environment; @Bean public Properties properties() { Properties properties = new Properties(); for (PropertySource<?> source : ((ConfigurableEnvironment) environment).getPropertySources()) { if (source.getSource() instanceof Properties) { log.info("Loading properties from property source " + source.getName()); Properties props = (Properties) source.getSource(); properties.putAll(props); } } return properties; } 

Note however that the order may be significant; you would probably want to load the system properties after other properties, so they can override application properties. In that case, add some more control code using source.getName() to pick out "systemProperties":

@Bean public Properties properties() { Properties properties = new Properties(); Properties systemProperties = null; for (PropertySource<?> source : ((ConfigurableEnvironment) environment).getPropertySources()) { if (source.getSource() instanceof Properties) { if ("systemProperties".equalsIgnoreCase(source.getName())) { log.info("Found system properties from property source " + source.getName()); systemProperties = (Properties) source.getSource(); } else { log.info("Loading properties from property source " + source.getName()); Properties props = (Properties) source.getSource(); properties.putAll(props); } } } // Load this at the end so they can override application properties. if (systemProperties != null) { log.info("Loading system properties from property source."); properties.putAll(systemProperties); } return properties; } 

Comments

0

Inject application context arguments in constructor and relay it into java.util.properties:

import java.util.Properties; import org.springframework.boot.ApplicationArguments; public MyComponentClass(ApplicationArguments arguments) { Properties properties = getProperties(arguments); } private static Properties getProperties(ApplicationArguments arguments) { Properties properties = new Properties(); for (String argementName : arguments.getOptionNames()) { List<String> argumentValues = arguments.getOptionValues(argementName); if (argumentValues.size() > 0) { properties.put(argementName, argumentValues.get(0)); } } return properties; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.