Spring not loading properties when applicationContext.xml is referenced in a @Configuration class
@Configuration
@ImportResource("classpath:applicationContext.xml")
public class SpringConfig {
@Autowired
private MyBean1 myBean1;
@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean(name = "myBean2")
public MyBean2 myBean2() {
MyBean2 bean2 = new MyBean2();
return bean2;
}
}
applicationContext.xml:
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:test.properties</value>
</property>
</bean>
<bean id="myBean1" class="com.foo.bar.MyBean1">
<property name="name" value="${name}" />
<property name="age" value="${age}" />
</bean>
Test.properties: (in the classpath)
name=foo
age=10
When I load the applicationContext.xml file using the following lines of code, it worked:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
I see the following lines printed:
2015-05-30 10:01:08.277 [INFO] org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:172 - Loading properties file from class path resource [test.properties]
2015-05-30 10:01:08.292 [INFO] org.springframework.beans.factory.support.DefaultListableBeanFactory:596 - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5c001eb0: defining beans [placeholderConfig,myBean1]; root of factory hierarchy
I have no issues loading the test.properties file with "myBean1" getting the value of ${name} and {age} from the properties file.
The issue I have is when I try to load SpringConfig:
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
The SpringConfig class refers to applicationContext.xml as: @ImportResource("classpath:applicationContext.xml")
The error I am seeing is:
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myBean1' defined in class path resource [applicationContext.xml]: Could not resolve placeholder 'name' in string value "${name}"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:174)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:151)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:669)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73)
In a nutshell, when I load applicationContext using ClassPathXmlApplicationContext, then I have no issue:
Working:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
But when it is referred by SpringConfig, then I see that applicationContext does not see my properties file.
Not Working:
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
Please note that test.properties is in my classpath and it is nothing to do with the properties file missing or something.
I don't know if I have to use a different approach for AnnotationConfigApplicationContext as I need myBean1 to be auto-wired into SpringConfig and myBean1 uses some properties from the test.properties file.
Best Answer
When using
you're registering two
PlaceholderConfigurerSupport
beans that are used to resolve properties. One through Javaand one through the imported XML
The
PropertySourcesPlaceholderConfigurer
bean is fail-fast when it comes to resolving properties. That is, if it doesn't find a match, it will throw an exception (actually the nested class that does the resolution will do that).Since your
PropertySourcesPlaceholderConfigurer
hasn't been initialized with anylocations
, it doesn't have any sources from where to resolve${name}
or${age}
(it has some sources, but not yourtest.properties
file).Either set up your bean correctly to find your properties file
or remove it entirely. If you do remove it, Spring will use the correctly configured
PropertyPlaceholderConfigurer
bean from XML.