Announcement Announcement Module
Collapse
No announcement yet.
context:property-placeholder does not register PropertySource(s) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • context:property-placeholder does not register PropertySource(s)

    I switched to Spring 3.1.0.M1 version and started using new features, including @Profiles and environment-specific beans.

    I currently have problems with PropertySources and profiles activation. Here is the story.

    In my root application context (not web one), I use
    Code:
    	<!-- Application properties -->
    	<context:property-placeholder location="
    		classpath:app.properties,
    		classpath:jdbc.properties
    		"/>
    Then, in my included contexts and annotated beans I use values from these files via Spring EL expressions like
    Code:
    	@Value("${i18n.country}")
    	public void setCountry(String country) {
    		this.country = country;
    	}
    This works great. So far so good.
    Then I added "spring.profiles.active" property to my app.properties. I need to do this because it is being populated by Maven and depends on active maven profiles turned on during the build. Value is successfully filtered by maven and app.properties contains correct data before application startup.

    But Spring profiles are not activated via this property located in app.properties. I investigated this problem and found that <context: property-placeholder> does not register its resources as Spring PropertySource(s).
    That surprised me a little, but I read blog post about profiles feature and decided that this property is read too late, after rootContext.refresh() is called.
    So, ok, I commented my property-placeholder out and created ApplicationInitializer that reads these 2 files and registers them as PropertySources. Ok, it was called successfully, but after that I got my @Value annotations broken, i.e. @Value("${i18n.country}") fails with exception about unresolved placeholder.

    So, my questions are:
    - do @Value annotations in particular and Spring EL in general use unified properties infrastructure now ?
    - should context: property-placeholder register itself as a PropertySource in current environment ?

    - if both previous answers are "no", then what is the correct way to make single source of application configuration (kinda one set of property files, attached via Spring in one place - either XML or java), so that @Value("${aaa}") annotations, bean values in XML configurations and rootCtx.getEnvironment().getProperty("aaa") are all return correct, equal values.

  • #2
    Any ideas?
    I can provide some additional code that I initially omitted (my AppInitializer and its web.xml binding, for example), but the problem is really in the final 3 questions. Just need to know how it should be.

    Comment


    • #3
      This is probably because the ApplicationContextInitializer you're registering is working against the child application context and not the parent (root) application context, where the placeholder replacement is needed.

      Are you registering the ACI as a context-param, or as an init-param to the DispatcherServlet? Pasting your web.xml would help.

      Comment


      • #4
        Thanks for reply, Chris.
        Here is the initializer class I tried:

        Code:
        public class AppInitializer extends PropertiesLoaderSupport 
        		implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
        	
        	private final static Logger logger = LoggerFactory.getLogger(AppInitializer.class);
        	
        	@Override
        	public void initialize(ConfigurableWebApplicationContext applicationContext) {
        		
        		try {
        			this.setLocations(applicationContext.getResources("classpath:*.properties"));
        			applicationContext.getEnvironment().getPropertySources().addLast(
        					new PropertiesPropertySource("app_properties", this.mergeProperties()));
        			
        		} catch (IOException ioe) {
        			logger.error("IO error during apllication properties initialization", ioe);
        			throw new RuntimeException(ioe);
        		}
        		
        		// perform any other initialization of the context ...
        	}
        	
        }
        And here is my web.xml binding:

        Code:
        	<!-- Application context initializer classes -->
        	<context-param>
        		<param-name>contextInitializerClasses</param-name>
        		<param-value>com.xxx.yyy.web.AppInitializer</param-value>
        	</context-param>
        So I actually did it just like you described in http://blog.springsource.com/2011/02...ty-management/.

        It is loaded via context-param, but initializer is ConfigurableWebApplicationContext-specific.

        I have @Value("${xxx}") annotations in both services and web controllers, so I need them to be resolved in both contexts - root and web ones.

        Comment


        • #5
          I've added an issue for this: https://jira.springsource.org/browse/SPR-8185

          Comment


          • #6
            @malexejev - the issue linked above is now resolved. It would be great if you would try it out and let us know how it goes! Please leave any such comments on the issue, thanks.

            This change will be available in the next snapshot - about an hour from the time of this post.

            Comment


            • #7
              Hi guys,

              I was running into a similar issue as malexejev where I had an ApplicationContextInitializer adding a PropertySource and the PropertySource wasn't getting sucked into the application context the app was actually using.

              Just tried it and things are now working for me with the latest snapshot. Thanks for the fix!

              Comment

              Working...
              X