简体   繁体   中英

Add properties to property placeholder

I have an application where a property placeholder is used to read properties, configured in applicationContext.xml :

...
<context:property-placeholder
     location="classpath*:META-INF/spring/*.properties"/> 
...

The application runs in an Tomcat and uses the parameter defined in context.xml. The application access this parameter like normal properties ( @Value(${cfma.applicationUrl}) ). This works

In my test cases I do not have this tomcat properties, so I want to add them "manually" to the application context. But also load the normal applicationContext.xml

testContext.xml:

<import resource="classpath:/META-INF/spring/applicationContext.xml" />
<context:property-placeholder properties-ref="simulatedTomcatProperties"/>
<util:properties id="simulatedTomcatProperties">
   <prop key="cfmt.applicationBaseUrl">localhost:8080/cfmt</prop>
</util:properties>

Now I have two context:property-placeholder and this does not work (of course) – So my question is, who can I extend the properties in the “normal” property-placeholder in my test?


More Explanation of what I need:

  • The productive environment (as well as the development environment) defines some properties via Tomcat parameter. Therefore they are not included in any properties file, but nerveless they can be accessed like normal properties ( @Value(${cfma.applicationUrl}) ). Moreover there must not be any Fallback, if the properties are not defined in the Tomcat, the application must not start!
  • In the test cases (that use the spring context) I must some how insert the property (cfma.applicationUrl) so that it can be injected in the annotated variables. But if I add an second context:property-placeholder they are not merged:

@See Comments on https://jira.springsource.org/browse/SPR-4881 -- they explain that behaviour.


When I talk about Tomcat parameter I am talking about somethink like this:

context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Parameter name="cfmt.applicationBaseUrl"
          value="http://localhost/demoApp" override="false"/>
</Context>

Not sure if this will help, but what I do in a similar situation is have 2 app.properties files with the same name, one in sec/test/resources and the other in src/main/resources. Now during testing the first is loaded because the test classes are first on the classpath, but when I deploy only the main one is there and so it is loaded.

Does it work if you add the same location attribute to the context:property-placeholder defined in testContext.xml that is in the one defined in applicationContex.xml ? You would also need to add the attribute local-override="true" to have the properties-ref override those from under META-INF .

Edit:

Given your most recent comment, I think that you will need to forgo using the context namespace and directly use the Spring objects that is uses behind the scenes. Perhaps something like this:

In applicationContext.xml:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath*:META-INF/spring/*.properties" />
</bean>

In testContext.xml:

<bean id="propertyConfigurerTest" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" parent="propertyConfigurer">
    <property name="properties" ref="simulatedTomcatProperties" />
    <property name="localOverride" value="true" />
</bean>
<util:properties id="simulatedTomcatProperties">
   <prop key="cfmt.applicationBaseUrl">localhost:8080/cfmt</prop>
</util:properties>

I'm guessing you want the local properties to override the properties defined from the classpath resources so I defined localOverride as true.

If, in your main applicationContext.xml, you specify several property lookups as listed below using a PropertiesFactoryBean, any missed properties files are not loaded, and the last successfully loaded properties file is used. In your case, default.properties (eg your test properties file) would be loaded, and because the second file:${catalina}... wouldn't be loaded, your @Value fields would be injected with values specified in default.properties.

Answer taken from here :

<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
   <property name="ignoreResourceNotFound" value="true" />
   <property name="locations">
      <list>
        <value>classpath:default.properties</value>
        <value>file:${catalina.home}/webapps/myProperties.properties</value>
      </list>
   </property>
</bean> 

I solved the problem by splitting up the applicationContext.xml in two files: - applicationContext.xml -- contains the "normal" bean, but NO include of applicationContext-properties.xml - applicationContext-properties.xml -- contains the property placeholder config

applicationContext-properties.xml :

 <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
      <property name="locations" value="classpath*:META-INF/spring/*.properties" />
      <property name="ignoreUnresolvablePlaceholders" value="false" />
 </bean>

The web application loads both files on startup:

web.xml :

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

For my tests I have added a propoperties file: simulatedTomcat.test-properties that contains all the tomcat properties. note: that this file does not match the pattern used by the properties placeholder configurer of applicationContext-properties.xml

Then I have an properties placeholder configurer for my test that load both kind op properties files ( *.properties and *.test-properties )

test-context.xml

<import resource="classpath:/META-INF/spring/applicationContext.xml" />
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
   <property name="locations">
      <list>
         <value>classpath*:META-INF/spring/*.properties</value>
         <value>classpath*:META-INF/spring/*.test-properties</value>
      </list>
   </property>
</bean>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM