Roy Truelove
Roy Truelove

Reputation: 22456

Spring environment properties from file

I'm trying to figure out how to get the values of a properties file into my Spring Environment properties.

The pre Spring 3.1 way of doing this would be something like:

  <context:property-placeholder location="classpath:my.properties" />

  <bean id="myBean" class="com.whatever.MyBean">
    <property name="someValue" value="${myProps.value}" />
    <!-- etc -->
  </bean>

I could have also done this:

public class MyBean {

   @Value(value = "#{myProps.value}")
   private String someValue;

}

Now that I can ostensibly pull properties from the Environment class, this seems like a much cleaner way of getting properties than using the clunky #{myProps.value} syntax in either my xml or my bean itself.

I tried this in my XML:

<bean
    class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="location">
        <value>classpath:my.properties</value>
    </property>
</bean>

But the properties are not added to Environment.

I understand that I can use the PropertySource attribute, but I'm not doing my configuration with annotations.

So how can I set up my bean / xml so that variables setup in my props are available in Environment? Moreover, how can I inject those values into my bean without having to explicitly say "environmentInstance.getProperty("myProps.value")?

Upvotes: 4

Views: 3671

Answers (2)

Boris Treukhov
Boris Treukhov

Reputation: 17774

For the web applications

If you want to have Environment populated before the XML bean definitions are processed, you should implement a ApplicationContextInitializer(), as described in the Spring Source blog

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.bank.MyInitializer</param-value>
</context-param>

Here is a slightly modified version of the example from the blog

public class MyInitializer implements
        ApplicationContextInitializer<ConfigurableWebApplicationContext> {
    public void initialize(ConfigurableWebApplicationContext ctx) {
        ResourcePropertySource ps;
        try {
            ps = new ResourcePropertySource(new ClassPathResource(
                    "my.properties"));
        } catch (IOException e) {
            throw new AssertionError("Resources for my.properties not found.");
        }
        ctx.getEnvironment().getPropertySources().addFirst(ps);
    }
  }

For the standalone applications

Basically the same thing, you can modify the environment of the AbstractApplicationContext directly

   ResourcePropertySource ps;
   try {
        ps = new ResourcePropertySource(new ClassPathResource(
                        "my.properties"));
   }catch (IOException e) {
                throw new AssertionError("Resources for my.properties not found.");
   }
   //assuming that ctx is an AbstractApplicationContext
   ctx.getEnvironment().getPropertySources().addFirst(ps);

P.S. the earlier version of this answer showed an attempt to modify the Environment from the bean but it seems to be an antipattern spreading on SO, because for sure you would like to have Environment property sources list populated even before the XmlBeanDefinitionReader starts to process XML to make placeholders work inside the <import/> statement.

Upvotes: 1

Biju Kunjummen
Biju Kunjummen

Reputation: 49915

My understanding is also a little addled but this is what I could make out:

  1. Environment is a way to indicate the currently active profiles (and profiles are a way to selectively create beans)
  2. PropertySources can be associated to an environment and the way to do that is using @PropertySource annotation, there does not seem to be an xml equivalent to do this.
  3. Your understanding actually should be the other way round, AFAIK: when you declare <context:property-placeholder the placeholder will resolve properties against the locally declared properties and can fallback on the property sources declared in the environment, environment itself does not get modified with the new properties. Again,the only way to add properties to the environment itself seems to be through the @PropertySource annotation

Upvotes: 0

Related Questions