I am using Spring version 4.0.6.RELEASE and am trying to have spring read from a properties file and use one of the resolved properties to provide a location to another properties file. My spring.xml file has the following:
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>classpath:version.properties</value>
<!- The below file contains the another file location -->
<value>file:${catalina.base}/conf/instance.properties</value>
<value>${another.file.location}</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
</bean>
instance.properties contains:
account.id=BlahBlahBlah
another.file.location=file:/Users/beardman/.myapp/local.properties
and /Users/beardman/.myapp/local.properties contains:
magic.number=3
database.endpoint=blah
I keep getting the following warning:
WARN [main] o.s.b.f.c.PropertyPlaceholderConfigurer Could not load properties from ServletContext resource [/${another.file.location}]: Could not open ServletContext resource [/${another.file.location}]
When debugging my code, I can see that the account.id was injected correctly, but I can never get the magic.number or database.endpoint to show up. How can I get spring to use the resolved property from the instance.properties file as the value for the another.file.location?
EDIT: Added property file contents
Spring by default replaces property placeholders with system properties. Since you want to use properties defined in an external file as well, you need to create a PropertyPlaceholderConfigurer
This tag is the shorthand, but you can define PropertyPlaceholderConfigurer as a bean if you need more control. Add this before your applicationProperties bean
<context:property-placeholder location="file:${catalina.base}/conf/instance.properties"/>
Note that properties in the file will override system properties in the default mode. You can specify that system properties are checked first by adding the attribute systemPropertiesMode="override" to the property-placeholder element
Related
In my applicationContext.xml file of my Spring project, I use a PropertyPlaceholderConfigurer manage the external properties from two configuration files, like this:
<!-- Configuration. -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${universign.configuration}</value>
<value>file:${universign.common.configuration}</value>
</list>
</property>
</bean>
The two file paths in the list are provided by system properties. My question is: How can I make the second value optional? When I launch the program, some times I want to launch with 1 configuraiton file, sometimes 2. But using my configuration above, if I don't provide the two system properties, the program cannot be launched, it will give an Exception like this:
[WARNING] Failed startup of context o.e.j.m.p.JettyWebAppContext#12f9f896{/,[file:///opt/li/projects/universign/universign-admin-www/webapp/, file:///opt/li/projects/universign/universign-admin-www/target/tmp/universign-config-8_17-SNAPSHOT-universign-admin-www_zip1/],UNAVAILABLE}{file:///opt/li/projects/universign/universign-admin-www/webapp/}
org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: ${universign.common.configuration} (Aucun fichier ou dossier de ce type)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:89)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
...
How to make one of the two configuration files optional?
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 jar containing a spring configuration. I am retrieving some JNDI variables to configure web service addresses inside the jar. Now, I am using the same jar in a Spring Batch and I would like to use the same spring configuration file.
My problem is that I am passing the web service addresses as system properties to my batch with the
java -DmyFoo=bar
Using this
<context:property-placeholder system-properties-mode="OVERRIDE" ignore-unresolvable="true" />
I can get my variables as #Value("myFoo")
So my question is: is there any way to be able to get my JNDI variables in my property placeholder? Or be able to get them as JNDI and then expose them in a property placeholder?
What I want to be able to do is replace this
<bean id="MBean" class="com.xxx.utils.ActivationMBean">
<property name="makeCall">
<jee:jndi-lookup jndi-name="semantic.activation" />
</property>
</bean>
By this
<bean id="MBean" class="com.xxx.utils.ActivationMBean">
<property name="makeCall" value="${semantic.activation}" />
</bean>
When using <context:property-placeholder /> a PropertySourcesPlaceholderConfigurer is registered. (That is when you are on Spring 3.1 or later and are using the xsd without version or a version > 3.0). The property-source abstraction has been added in Spring 3.1.
The PropertySourcesPlaceholderConfigurer uses the configured PropertySources to obtain values for placeholders. The PropertySources consulted depends on the environment, web or non-web, and the amount of #PropertySource annotations or loaded property files through the location attribute of the <context:property-placeholder /> elements.
For the StandardServletEnvironment (web) the PropertySources are consulted in the following order.
ServletContext init-params
ServletContext context-params
JndiPropertySource
System Properties
System Environment
For the StandardEnvironment (non-web) the PropertySources are consulted in the following order.
System Properties
System Environment
Depending on the setting of the localOverride property properties loaded from properties files are added to the top (true) or to the bottom (false) of the list of PropertySources to consult.
Given the following bean definition.
<bean id="MBean" class="com.xxx.utils.ActivationMBean">
<property name="makeCall" value="${semantic.activation}" />
</bean>
In a web environment the placeholder ${semantic.activation} is being resolved first against the JNDI tree if that isn't found it will fallback to the System Properties. For a non-web no JNDI lookup is attempted and properties specified by -D or in the environment are consulted.
I finally found a trick that makes what I need:
<bean id="MBean" class="com.xxx.utils.ActivationMBean">
<property name="makeCall">
<jee:jndi-lookup jndi-name="semantic.activation" default-value="${semantic.activation}" />
</property>
</bean>
It can't be used with the #Value annotation but if we are using JNDI it will take it and not it will fall back to the property. If none is defined it will fail to start and that is what I wanted.
I want to read properties file from WEB-INF folder and not from the classpath since I dont want to compile my application again if I make any modifications. My file is coming in build in the directory but when I am trying to acces its not showing anything. Please can anyone help me with this. I am using Spring framework. So if there is any method in Spring which will allow us that we are not required to compile our application again and again and the modifications are taken up by the applications on its own.
Add this to your application context configuration file and try.
<bean id="applicationProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>yourPropertiesFile.properties</value>
</list>
</property>
</bean>
To access properties from the properties file, use the bean's ID in your class which must be annotated with #Service or #Component
#Resource(name="applicationProperties")
private Properties anyVariableName;
...
...
String propValue = anyVariableName.getProperty("propertyName");
You can put the properties file in the resources folder. It will not require recompiling of the application.
In spring you can use the following lines to read the property values from property file :
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:dash_conf.properties</value>
</list>
</property>
</bean>
Also if you want to read the property file from java class you can use :
InputStream in = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(fileName);
Properties prop = new Properties();
prop.load(in);
Hope this solves your problem.
Before post this Question, I google to get Properties from Spring project(Its NOT web-based project). I am confused as every one are talking about application-context.xml and have configuration like
However, I am working on normal Java Project with Spring(NO Web-app and stuff like that). But I would like to get some common properties from properties file and that needs to be used in JAVA file. How can achieve this by using Spring/Spring Annotations?
Where I should configure myprops.properties file under my project and how to invoke through spring?
My understanding is application-context.xml is used ONLY for web based projects. If not, how should I configure this application-context.xml as I do NOT have web.xml to define the application-context.xml
You can create an XML based application context like:
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
if the xml file is located on your class path. Alternatively, you can use a file on the file system:
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
More information is available in the Spring reference docs. You should also register a shutdown hook to ensure graceful shutdown:
ctx.registerShutdownHook();
Next, you can use the PropertyPlaceHolderConfigurer to extract the properties from a '.properties' file and inject them into your beans:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
Lastly, if you prefer annotation based config, you can use the #Value annotation to inject properties into you beans:
#Component
public class SomeBean {
#Value("${jdbc.url}")
private String jdbcUrl;
}
As of Spring 4, you can use the #PropertySource annotation in a Spring #Configuration class:
#Configuration
#PropertySource("application.properties")
public class ApplicationConfig {
// more config ...
}
If you would like to have your config outside of your classpath, you can use the file: prefix:
#PropertySource("file:/path/to/application.properties")
Alternatively, you can use an environmental variable to define the file
#PropertySource("file:${APP_PROPERTIES}")
Where APP_PROPERTIES is an environmental variable that has the value of the location of the property file, e.g. /path/to/application.properties.
Please read my blog post Spring #PropertySource for more information about #PropertySource, its usage, how property values can be overridden and how optional property sources can be specified.
You don't have to use Spring.
You can read with plain java like this:
Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
Can you figure out how your project will be used in the whole app? If your project is used as a build path for a web app and the configuration in your project is achieved through spring annotations, so no doubt you are puzzled about how to add an application.xml file. My suggest is you have to announce the guys who will use your project, tell them what you need and you just need to add #Value("${valuename}") in your code.
Create new property file inside your src/main/resources/ directory and file extension must be .properties e.g. db.properties
Write following context properties in your spring xml configuration file:
<context:property-placeholder location="db.properties"/>
Usage: ${property-key}