Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 3.1 PropertySourcesPlaceholderConfigurer and conditional import

Looking at the new spring property support in 3.1 ( http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/ ), it looks like this should be possible:

<context:property-placeholder location="/WEB-INF/application-customer-dev.properties,classpath:application-customer.properties" ignore-resource-not-found="true"/>

<import resource="classpath*:com/x/core/security/security-${login.security}.xml"/>

where login.security is in application-customer-dev.properties as:

login.security=dev

(and security-dev.xml does exist in the appropriate place). I am missing something though, as login.security is not able to be resolved. I would expect this behavior in versions of spring prior to 3.1, but it looks like this should be valid with 3.1 (which we are using)?

like image 889
Kurt Peterschmidt Avatar asked Feb 09 '12 21:02

Kurt Peterschmidt


1 Answers

Footnote [2] of your link:

[2]: Because processing of <import/> elements necessarily occurs before BeanFactoryPostProcessors are invoked, meaning that even PropertyPlaceholderConfigurer could not help here. Because the Environment and its set of PropertySources are configured before container refresh, placeholders in elements can be resolved against the Environment without any lifecycle issues.

UPDATE:

According to the javadoc for PropertySourcesPlaceholderConfigurer, PropertySourcesPlaceholderConfigurer is a BeanFactoryPostProcessor, so what the footnote really says is that the import is resolved before the PropertySourcesPlaceholderConfigurer is installed, so it will not work either (in fact, at the time the <import/> is resolved, the configurer might not even exist yet!) Yes, when it is installed it will look at the Environment, but you cannot use it to resolve inside an <import/>, because at that time no postprocessors are operative. And that includes PropertySourcesPlaceholderConfigurer.

Basically Spring XML context setup goes more or less like this:

  1. Context is created.
  2. Environment is set.
  3. XML is read (all XML, resolving imports if necessary). Bean definitions are created.
  4. BeanFactoryPostProcessors are installed and invoked, processing bean definitions.
  5. BeanPostProcessors are installed.
  6. Beans are instantiated according to the bean definitions. BeanPostProcessors are applied.

This is a similar problem as that which causes that you cannot use the order property of many postprocessors to apply a BeanPostProccesor before a BeanFactoryPostProcessor (to do something like make a PropertyPlaceholderConfigurer resolve placeholders from a @PersistenceContext): the behaviour is hardcoded in the Spring application context, so you have to work around it by specializing some Spring classes.

like image 123
gpeche Avatar answered Sep 21 '22 05:09

gpeche