How to initialize property-placeholder with environment attached to the current application context in Spring?

StackOverflow https://stackoverflow.com/questions/21304898

Question

I'm using Spring Framework 3.2.6.RELEASE.

I'm trying to set properties using command line interface (using JOptCommandLinePropertySource) via

PropertySource<?> propertySource = new JOptCommandLinePropertySource(options);
final GenericApplicationContext context = new GenericApplicationContext();
context.getEnvironment().getPropertySources().addFirst(propertSource);
...

I have this beans configurer:

package com.example;

@Configuration
public class AppConfig {
  @Value("${prop1}")
  private String prop1;

  @Bean
  public MyBean myBean() {
    MyBean ret = new MyBean();
    ret.init(prop1);
    return ret;
  }
}

I'm starting my program with command line argument: --prop1=prop_value

If I do initialization with this xml:

<beans>
  <context:annotation-config />
  <context:property-placeholder />
  <context:component-scan base-package="com.example" />
</beans>

Then I get this error: Could not resolve placeholder 'prop1' in string value "${prop1}"

13:47:36.932 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected method of bean 'AppConfig': AutowiredFieldElement for private java.lang.String com.example.AppConfig.prop1
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AppConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.example.AppConfig.prop1; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'prop1' in string value "${prop1}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
...

But with this xml all works fine:

<beans>
  <context:annotation-config />
  <context:component-scan base-package="com.example" />

  <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="environment" ref="environment" />
  </bean>
</beans>

Why PropertySourcesPlaceholderConfigurer does not check current application context's environment as it defined in Javadoc?

Specialization of PlaceholderConfigurerSupport that resolves ${...} placeholders within bean definition property values and @Value annotations against the current Spring Environment and its set of PropertySources.

Was it helpful?

Solution

When using namespace configuration it is recommended to use the version-less xsd. So instead of http://www.springframework.org/schema/context/spring-context-2.5.xsd one is adviced to use http://www.springframework.org/schema/context/spring-context.xsd. This ensures that spring will use the most recent version of the xsd available on the classpath.

With regard to <context:property-placeholder /> there where some, breaking(?), changes in Spring 3.1 in regards to the default configuration. Prior to Spring 3.1 the default-value for the system-properties-mode attribute was FALLBACK, which in Spring 3.1 leads to the creation of a PropertyPlaceholderConfigurer instead of a PropertySourcesPlaceholderConfigurer. The default is configured in the specific xsd. (As if Spring 3.1 it is ENVIRONMENT).

So using an older xsd leads to the default behavior belonging to that specific version of the xsd, switch to either the 3.2 xsd or the version-less xsd. (As mentioned the latter is recommended).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top