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:
@Value(${cfma.applicationUrl})
). Moreover there must not be any Fallback, if the properties are not defined in the Tomcat, the application must not start! 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.