Reputation: 1175
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.
Upvotes: 2
Views: 15799
Reputation: 279880
When using
new AnnotationConfigApplicationContext(SpringConfig.class);
you're registering two PlaceholderConfigurerSupport
beans that are used to resolve properties. One through Java
@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
and one through the imported XML
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:test.properties</value>
</property>
</bean>
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 any locations
, it doesn't have any sources from where to resolve ${name}
or ${age}
(it has some sources, but not your test.properties
file).
Either set up your bean correctly to find your properties file
@Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setLocation(new ClassPathResource("test.properties"));
return propertySourcesPlaceholderConfigurer;
}
or remove it entirely. If you do remove it, Spring will use the correctly configured PropertyPlaceholderConfigurer
bean from XML.
Upvotes: 6