in my Spring configuration I have the following line:
<context:property-placeholder
location="/META-INF/spring/global.properties,#{systemProperties['external.propertyFile'] ?: ''}, /WEB-INF/local.properties"
ignore-resource-not-found="true" />
My intention is to have some defaults shipped in global.propertiesand these should be overridable by another external file passed in through external.propertyFile and some properties are kept local by the application itself in local.properties
From what I see in the logs - global.propertiesand local.properties are processed right but the substitution with #{systemProperties ... } doesn't seem to work here.
Any hint's how to fix that or work around it?
Here's the related log from my app (shortened a bit):
Loading properties file from ServletContext resource [/META-/spring/counter.properties]
Loading properties file from ServletContext resource [/#{systemProperties['external.propertyFile'] ?: ''}]
WARN support.PropertySourcesPlaceholderConfigurer: Could not load properties from ServletContext resource [/#{systemProperties['external.propertyFile'] ?: ''}]: Could not open ServletContext resource [/#{systemProperties['external.propertyFile'] ?: ''}]
Loading properties file from ServletContext resource [/WEB-INF/local.properties]
Just a remark:
In other places of the same XML configuration the substitution works fine - eg. with:
<util:properties
id="myProp"
location="#{systemProperties['my.propertyFile'] ?: '/META-INF/spring/my.properties'}"/>
But this time I need a more complex way to handle/merge the actual property values :(
This worked OK for me
<context:property-placeholder
location="/META-INF/spring/global.properties,${external.propertyFile},/WEB-INF/local.properties"
ignore-resource-not-found="true" />
Related
I used the following configuration in my applicationContext.xml
<context:property-placeholder location="classpath:system.properties,file:/data/conf/system.properties,file:/data/conf/1033.properties" ignore-unresolvable="true" />
to load some placeholders:
use these properties defined in classpath:system.properties;
if file or properties exist in /data/conf/system.properties, use them instead of above;
if file or properties exist in /data/conf/1033.properties, use them instead of above.
Now Spring started ok if both /data/conf/system.properties and /data/conf/1033.properties exists, but it will throw rg.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: ... if either of them does not exist.
How to tell spring load these properties but ignore missing ones.
You have to add ignore-resource-not-found="true"
<context:property-placeholder location="classpath:system.properties,file:/data/conf/system.properties,file:/data/conf/1033.properties"
ignore-unresolvable="true"
ignore-resource-not-found="true"/>
I am learner of spring have build my test project with spring IOC container and have configure beans.xml in my project root path and load into my application and get bean from it.
spring.xml in project root directory
BeanFactory bean = new XmlBeanFactory(new FileSystemResource("spring.xml"));
spring.xml in source file
BeanFactory bean = new XmlBeanFactory(new FileSystemResource("src/spring.xml"));
this is another code to load beans.xml file
ApplicationContext context = new GenericXmlApplicationContext("beans.xml");
my question is that is there any standards or conventions for creation of xml file name and location of file in real project.because in some reading articles i also found that there might be multiple xml files for large project like service.xml and dao.xml.
It can be useful to have bean definitions span multiple XML files. Often each individual XML configuration file represents a logical layer such as defining DAO beans etc. in your architecture but you should always place your XML configuration files under src/resources and access them as
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
From the Spring's Manual:
You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple Resource locations, as was shown in the previous section. Alternatively, use one or more occurrences of the element to load bean definitions from another file or files. For example:
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
</beans>
I want to read an external properties file when launching Jboss 4.2 . I want to add it to the classpath to read it from a WAR file . I have seen different solutions with Jboss 6 using modules, but I haven't seen anything related to JBoss 4.2.
I have included inside 'jboss-service.xml' the following code :
<!-- Bean for reading properties -->
<mbean code="org.jboss.varia.property.SystemPropertiesService"
name="jboss.util:type=Service,name=SystemProperties">
<!-- Load properties from each of the given comma separated URLs -->
<attribute name="URLList">
./conf/path.tmview.properties
</attribute>
</mbean>
In this file I have defined the property :
property-placeholder filepath=/var/tmview_props/tmview/tmview.properties
This property is used in the following bean definition
<bean id="tmviewConfigurerLocation" class="org.springframework.core.io.FileSystemResource">
<constructor-arg value="${property-placeholder-filepath}" />
</bean>
inside an applicationContext.xml . When I launch jboss, the file of properties is read
15:45:29,939 INFO [SystemPropertiesService] Loaded system properties
from: file:/D:/devel/projects/tmview/deployment/jboss-
...ver/tmview/conf/path.tmview.properties
So, the property is read, but I kept obtaining the following exception
2015-03-24 15:45:39,219 ERROR
[org.springframework.web.context.ContextLoader] Context
initialization failed
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: ${property-placeholder-filepath} (The
system cannot find the file specified)
at
org.springframework.beans.factory.config.PropertyResourceConfigurer.
postProcessBeanFactory(PropertyResourceConfigurer.java:78)
Is there any special way to read the property inside the spring bean ?
In jboss 4 you was able to drop property files in the <jboss_home>/server/<instance>/conf directory and they would be available from the classpath.
Another possibility is add your custom directory to the classpath, to do this see Adding second conf folder to JBoss 5.1.0
Ok . At the end , I solved the problem . It seems the problem was located in reading from application-context.xml .
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:${tmview.conf.variables}</value>
</property>
</bean>
I had to add a property placeholder reader . Regarding to jboss, you can read the parameter file either from conf/jboss-service.xml or deploy/properties-receive.xml, but it seems more appropiate to do the reading from the second one .
I have a Spring-based web application running in a tomcat container and I want to maintain two different configuration files:
src/main/resources/default.properties: contains defaults for development, integration tests and when no other properties are set
.../tomcat/conf/app.properties: has a different content on different environments and should override default.properties
I have a spring configuration that is working fine when the application runs in a tomcat
app-context.xml
<context:property-placeholder
ignore-resource-not-found="true"
ignore-unresolvable="true"
system-properties-mode="OVERRIDE"
location="classpath:default.properties,
file:${catalina.home}/conf/app.properties"/>
But when I try to use this configuration in an integration test, outside of a tomcat container, loading the applicationContext fails:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308)
...
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0' defined in null: Could not resolve placeholder 'catalina.home'
at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:287)
Is there any way to tell Spring to ignore the location file:${catalina.home}/conf/app.properties when the property catalina.home is not set in the current context?
Since you have a context, where some PP values may be unresolved you can try to use a default variant for the property:
file:${catalina.home:}/conf/app.properties
In this case the path prefix is resolved to the empty String if there is no catalina.home property, e.g. in the System.getProperties(), which is the case for Tomcat, I guess.
And after that the ignore-resource-not-found="true" does the stuff.
you can set ignore-resource-not-found to solve this problem.
Try this:
<context:property-placeholder
ignore-resource-not-found="true"
ignore-unresolvable="true"
system-properties-mode="OVERRIDE"
location="classpath:default.properties,
file:${catalina.home}/conf/app.properties"/>
Code snippet from spring-context.xsd:
<xsd:attribute name="ignore-resource-not-found" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies if failure to find the property resource location should be ignored.
Default is "false", meaning that if there is no file in the location specified
an exception will be raised at runtime.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
What I'd suggest is using spring profiles to enable/disable property files.
When running in tomcat swith on the "tomcat" or "web" profile and put the loading of the app.properties into that profile.
In my Spring application, I have a simple properties file located in folder WEB-INF\classes so that it, the DispatcherServlet and various other config files are in the classpath.
The props file is defined in the DispatcherServlet as:
<bean id="propertiesFactory" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>/WEB-INF/classes/library.properties</value>
</property>
</bean>
The propertiesFactory bean is injected into a controller:
#Autowired
private Properties propertiesFactory;
And used in a one of the controller's methods as:
if (adminPassword.equals(propertiesFactory.getProperty("adminPassword"))) {
This all works perfectly, except for a test program as follows which has line:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("library-servlet.xml");
Which throws a BeanCreationException:
Injection of autowired dependencies failed
Because of:
java.io.FileNotFoundException: class path resource [WEB-INF/classes/library.properties] cannot be opened because it does not exist
But if the whole application can see the props file, why not this one program?
Everything in WEB-INF/classes is added to the root of the classpath. As such, you need to refer to your resource simply as
library.properties
or better yet
classpath:library.properties
in
<property name="location">
<value>classpath:library.properties</value>
</property>
You may find it useful to run
System.out.println(System.getProperty("java.class.path"));
and see what was used as classpath entries.