Passing path to a file in resources folder to spring bean definition - spring

I have a spring bean definition as:
<bean class="...">
<property name="myFile" value="full\path\to\src\main\resources\a\b\myfile.dat"></property>
</bean>
This works fine. But its full path. I intend it to be like:
value="a\b\myfile.dat"
While trying to do so, I get FilesNotFoundException.
How to do it correctly?

Good day,
You have to read a file through ClassPathResource, here is a good example - https://www.baeldung.com/spring-classpath-file-access

Related

How to locate the properties file in the spring context configuration file

I am using spring web mvc project, and I put all the spring related files under WEB-INF\spring, including a ormlite.xml and a jdbc.properties.
Now I want to locate the jdbc.properties file in the ormlite.xml,Like this:
<context:property-placeholder location="/WEB-INF/spring/jdbc.properties"/>
But when I run the application ,it will told me that :
Could not load properties
It can not find the properties file.
What is the problem?
From Spring forum:
The problem is that /WEB-INF isn't accessible as it isn't in the root
of the path, you must use the same path as you use in your test case
(include the src/main/webapp part but that will break your application
from running).
I suggest you move the jdbc.properties to the src/main/resources
directory and simply use classpath: prefix to load the properties.
Code:
<context:property-placeholder location="classpath:jdbc.properties"/>
The code above assumes they are on the root of the classpath (which is
where they are when they are in src/main/resources).
I hope this can help someone else.
I had the same problem - property files outside the classpath.
My solution:
First define a properties bean:
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>/WEB-INF/your.properties</value>
</property>
</bean>
Then reference it in the property-placeholder:
<context:property-placeholder properties-ref="configProperties" />
Works perfectly well for me!
Instead of:
<context:property-placeholder location="/WEB-INF/spring/jdbc.properties"/>
Use:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/spring/jdbc.properties"/>
And your properties will be available in Spring file, and don't forget to add a namespace: xmlns:p="http://www.springframework.org/schema/p"
I think you're missing the prefix to instruct Spring how to attempt to load the properties. I think your definition needs to be:
<context:property-placeholder location="file:/WEB-INF/spring/jdbc.properties"/>
Note the addition of the file: prefix.

Spring context:property-placeholder can't resovle nested variables

I have two projects -- project-web, and project-service, both of them use Spring core 3.1.3 and have configurations to load properties from corresponding property files:
project-web -- Spring Integration based project, in its spring config file:
<context:property-placeholder location="WEB-INF/spring-integration/spring-integration.properties" ignore-resource-not-found="true" />
<import resource="classpath*:META-INF/spring/applicationContext.xml" />
where the import is to include the spring configuration file from project-service, and in the project-service project, I have following configured:
<context:property-placeholder location="classpath:META-INF/application.properties, classpath:META-INF/db.properties" ignore-resource-not-found="true"/>
<import resource="classpath:META-INF/spring/applicationContext-data.xml"/>
where the import to include Spring configuration for the DAOs, inside the applicationContext-data.xml I have:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.${db.type}.driver}" />
<property name="url" value="${db.${db.type}.url}"/>
<property name="username" value="${db.${db.type}.username}" />
<property name="password" value="${db.${db.type}.password}" />
</bean>
When I run the unit tests for project-service, everything is fine, all the variables are resolved correctly without any problem. But when I run the project-web (project-service will be included as a .jar file in the WEB-INF/lib folder of project-web), it throws error during start up saying can't resolve ${db.type}:
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [META-INF/spring/applicationContext-data.xml]: Could not resolve placeholder 'db.type' in string value "db.${db.type}.driver"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209) ~[spring-beans-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:174) ~[spring-context-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:151) ~[spring-context-3.1.3.RELEASE.jar:3.1.3.RELEASE]
......................
Note: I can't declare everything in the project-web, because project-service will be also used by other projects. Anyone know why in project-service works when it runs alone but not when included by the project-web? It can't resolve the nested variable ${db.type}
The problem is that your first PropertyPlaceHolderConfigurer is trying to resolve the placeholder that needs to be resolved by the second one.
You can either use a different prefix for each one (e.g. !{ instead of ${ for one of them), or set
ignore-unresolvable="true"
on the first one - then it will leave the resolution to the other one.

Spring application context external properties?

i have a Spring application and its working well so far. Now i want the properties file in an external config folder and not in the packed jar to change things without the need to repack. This is what i got:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- <property name="locations" value="classpath:/springcontext.properties"/> -->
<property name="locations" value ="config/springcontext.properties" />
The outcommented one is working and the other one i dont get to work :/ Can someone help?
Edit:
Thx 4 comments so far.
Maybe my question wasnt clear enough :). I perform a Maven build and everything will be packaged and i want this folder to be NOT in the package nut next to the outcomming jar and in this folder i want the properties file. possible?
You can try something like this:
<context:property-placeholder
location="${ext.properties.dir:classpath:}/servlet.properties" />
And define ext.properties.dir property in your application server / jvm, otherwise the default properties location "classpath:/" (i.e., classes dir of .jar or .war) would be used:
-Dext.properties.dir=file:/usr/local/etc/
BTW, very useful blog post.
You can use file prefix to load the external application context file some thing like this
<context:property-placeholder location="file:///C:/Applications/external/external.properties"/>
<context:property-placeholder location="classpath*:spring/*.properties" />
If you place it somewhere in the classpath in a directory named spring (change names/dirs accordingly), you can access with above
<property name="locations" value ="config/springcontext.properties" />
this will be pointing to web-inf/classes/config/springcontext.properties
This blog can help you. The trick is to use SpEL (spring expression language) to read the system properties like user.home, to read user home directory using SpEL you could use #{ systemProperties['user.home']} expression inside your bean elements. For example to access your properties file stored in your home directory you could use the following in your PropertyPlaceholderConfigurer, it worked for me.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:#{ systemProperties['user.home']}/ur_folder/settings.properties</value>
</property>
</bean>
This question is kind of old, but wanted to share something which worked for me. Hope it will be useful for people who are searching for some information accessing properties in an external location.
This is what has worked for me.
Property file contents:
PROVIDER_URL=t3://localhost:8003,localhost:8004
applicationContext.xml file contents: (Spring 3.2.3)
Note: ${user.home} is a system property from OS.
<context:property-placeholder system-properties-mode="OVERRIDE" location="file:${user.home}/myapp/latest/bin/my-env.properties"/>
<bean id="appsclusterJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">${PROVIDER_URL}</prop>
</props>
</property>
</bean>
${PROVIDER_URL} got replaced with the value in the properties the file
One way to do it is to add your external config folder to the classpath of the java process. That's how I've often done it in the past.
<context:property-placeholder location="file:/apps/tomcat/ath/ath_conf/pcr.application.properties" />
This works for me.
Local development machine path is C:\apps\tomcat\ath\ath_conf and in server /apps/tomcat/ath/ath_conf
Both works for me

Spring PropertyPlaceholderConfigurer not replacing placeholder

I want to pass the WSDL url for an internal web service into my Spring beans.xml dynamically, using a PropertyPlaceHolderConfigurer.
Here's the scenario:
My web application is deployed in WebLogic 10.3.
The WSDL url is contained in a properties file that is located outside my application (directly under the corresponding domain folder, while my application is inside the autodeploy folder). I set the location of this properties file in my domain's setDomainEnv.cmd file like below:
set JAVA_PROPERTIES=%JAVA_PROPERTIES% %CLUSTER_PROPERTIES% -Dproperty.file.path.config=%DOMAIN_HOME%\Service.properties
This is what my Service.properties file contains:
Service.WSDL.PATH=http://localhost:8088/mockServiceSoap?WSDL
My Spring beans.xml configuration:----
<bean id="file.path" class="java.lang.System" factory-method="getProperty">
<constructor-arg index="0"><value>property.file.path.config</value></constructor-arg>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" ref="file.path"/>
</bean>
<bean id="myServiceId" class="com.test.service.ServiceImpl">
<property name="myServiceSoap">
<ref bean="myService"/>
</property>
</bean>
<bean id="myService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="serviceInterface" value="com.test.service.ServiceSoap"/>
<property name="wsdlDocumentUrl" value="${Service.WSDL.PATH}"/>
</bean>
I enabled DEBUG log specifically for PPC and this is what I saw in my application log:
INFO org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 178 - Loading properties file from URL [file:D:/bea10.3/user_projects/domains/my_domain/Service.properties]
So, it seems that although the Service.properties file is getting loaded by PPC, the ${Service.WSDL.PATH} is NOT getting replaced.
What am I doing wrong here?
Also, how can I find out if PPC tried replacing the value of the placeholder and with what value? I was hoping the log file would contain that info but there was nothing there.
Any help is appreciated.
I've figured out, that PropertyPlaceholderConfigurer needs to be declared first in the application Context file, otherwise there's no guarantee of the load order. It took me a few hours to realize this.
Try moving the "file.path" bean into the PropertyPlaceHolderConfigurer's location property.

Spring alias not available when running in Grails

I have a problem with Spring aliases in Grails. I have a library .jar file containing classes and Spring configuration that is not working as expected. It does work as expected when I import them from a standard (no Grails) Java app.
The current configuration contains this.
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="uk.co.company.package"/>
</bean>
<alias name="marshaller" alias="unmarshaller"/>
And fails with an error.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'unmarshaller' is defined
Changing the configuration to the following then leads it to work as expected.
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="uk.co.company.package"/>
</bean>
<bean id="unmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="uk.co.company.package"/>
</bean>
The configuration is being imported and is being read. For some reason the alias is unavailable when I try to use it. What is that reason?
This is with Grails 1.3.7 and Spring 3.0.5.
I am seeing this issue as well. You can get around it by defining the alias in the Grails resources.xml or in my case in my plugin doWithSpring closure:
springConfig.addAlias "aliasName", "beanName"
I'd expect the importBeans to import alias as well
This link might be helpful for you:
http://burtbeckwith.com/blog/?p=85
It is mentioned there that aliases don't work at least when declared in the resources.xml. The post also mentions a way of declaring aliases programatically. But it seems like this post was written a while back and not sure how relevant it is with grails 1.3.7.

Resources