Full path as a bean property in Spring - java

Say, I have the following bean in Spring context:
<bean class="some.class.BlabBlahBlah">
<property name="location" value="classpath:somefile.xml"/>
</bean>
Currently somefile.xml is placed in the src/main/java, but I'd like to place it somewhere in the file system. Is there a way to do that? I tried to set full path instead of this classpath: but it didn't work. Thanks in advance.

By reference (Table 4.1), you should probably use a file system resource path:
<property name="location" value="file:/path/to/file.xml" />

Related

Spring - how to use PropertyPlaceholderConfigurer to dynamically load files

i have the next properties files with Spring Framework
config.properties
with content
environment=devel //posible values: devel, testing, prod
and with the previous environment property, choose some of the following files to load dynamically
config-service1-devel.properties
config-service1-testing.properties
config-service1-prod.properties
config-serviceN-devel.properties
config-serviceN-testing.properties
config-serviceN-prod.properties
and then, with spring i want load the properties, i'm solve to load the first properties file but i dont understand how to use expression language to complete the values of the dependent properties.
<bean id="MainApplicationProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"
value="file://#{systemProperties['jboss.server.home.dir']}/conf/services.properties" />
<property name="placeholderPrefix" value="$mainProperty{" />
<property name="placeholderSuffix" value="}" />
</bean>
<bean id="SecondApplicationProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
depends-on="MainApplicationProperties">
<property name="locations">
<list>
<value>file://#{systemProperties['jboss.server.home.dir']}/conf/serviceOne/service1-$mainProperty{environment}.properties</value>
<value>file://#{systemProperties['jboss.server.home.dir']}/conf/serviceTwo/service2-$mainProperty{environment}.properties</value>
<value>file://#{systemProperties['jboss.server.home.dir']}/conf/serviceN/serviceN-$mainProperty{environment}.properties</value>
</list>
</property>
</bean>
the error output is the next,
java.io.FileNotFoundException: /..../conf/serviceOne/service1-$mainProperty{environment}.properties (No such file or directory)
my opinion is, the value has not replaced
helpme, thanks
The problem is that when BeanFactoryPostProcessors are starting to be invoked, they are already instantiated. So even thou the first PropertyPlaceholderConfigurer modifies the bean definition of the second PropertyPlaceholderConfigurer, it has no effect as both beans have been already instantiated.

Is it possible to specify a context property placeholder at runtime

I have a standalone jar that uses spring. The config in my spring xml uses placeholders of which I've been replacing when compiling with maven. Example spring config:
<bean id="foo" class="package.Foo">
<property name="host" value="${db.host}" />
</bean>
Instead of replacing ${db.host} using maven I'd like to pass in a properties file at runtime, e.g.
java -jar Application.jar productionDB.properties
This would allow me to switch the db host at runtime by passing in the production db properties file or the testing db properties file.
Is it possible to do this or are there any better ways of achieving the same goal?
You could specify your property file as a System Property, e.g.:
java -jar Application.jar -DappConfig=/path/to/productionDB.properties
Then you should be able to reference that in your application context:
<context:property-placeholder location="file:${appConfig}"/>
<bean id="foo" class="package.Foo">
<property name="host" value="${db.host}" />
</bean>
You could use a PropertyPlaceholderConfigurer to use a .properties file to pass in the required variables.
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:productionDB.properties</value>
</list>
</property>
</bean>
You can leave your bean declaration as is. The properties will be automatically taken from the productionDB.properties file.
There are a few options:
Set your resources via your container's JNDI and use Spring's <jee:jndi-lookup/>.
Use Spring's <context:property-placeholder location="classpath:/myProps.properties" />. I prefer this short-hand over the "full" bean definition because Spring will automatically use the correct implementation (PropertyPlaceholderConfigurer for Spring < 3.1, or PropertySourcesPlaceholderConfigurer for Spring 3.1+). Using this configuration, you would just drop the myProps.properties at the root of your classpath (${TOMCAT_HOME}/lib for example).
You can pass the values using the context:property-placeholder. So your setup would be something like:
<context:property-placeholder location="file://opt/db.properties"/>
Then when you are wiring up your Foo service, you can use the property names in your config, such as
<bean id="foo" class="package.Foo">
<property name="host" value="${db.host}" />
</bean>
Then just use the different set of files for each environmnet
See the spring docs for more details.

How do I use a variable property file name in Spring?

I'm trying to separate an application's configuration files from its war.
I want to keep all properties files in a directory on the disk. Then, the only property required inside the war would be the path to the configuration directory (let's say that would be in a file named config.properties):
config.dir = /home/me/config
Now in the spring configuration, I want to load this file (so that I know where the others are), and then the external files:
<bean id="propertySourcesPlaceholderConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:META-INF/config.properties</value>
<value>${config.dir}/other.properties</value>
</list>
</property>
</bean>
But this doesn't work, the placeholder is not resolved:
java.io.FileNotFoundException: class path resource [${config.dir}/config.properties] cannot be opened because it does not exist
I also tried using a separate bean of type PropertySourcesPlaceholderConfigurer - it didn't help much.
Do you know how I could accomplish this?
The problem is that the configurer bean has to be fully constructed before it can resolve placeholders in the other bean definitions in the context, so you can't use a placeholder expression in the definition of the configurer that would need to be resolved by the configurer itself.
You could instead put the path to your config dir into web.xml as a context-param
<context-param>
<param-name>configDir</param-name>
<param-value>/home/me/config</param-value>
</context-param>
and then access it as #{contextParameters.configDir} in your Spring config
<bean id="propertySourcesPlaceholderConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>#{contextParameters.configDir}/other.properties</value>
</list>
</property>
</bean>
Or you may be able to do it with two separate configurer beans with different values of placeholderPrefix, one loading the config.properties and then filling in the #{config.dir} placeholder in the other, which then loads the external config file.
This can be resolved by registering a PropertySource for the default environment. One of the ways this can be done is using Java Configuration:
#Configuration
#PropertySource("classpath:META-INF/config.properties")
public class MyConfig {
}
With this in place the placeholder should get resolved:
<bean id="propertySourcesPlaceholderConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>${config.dir}/other.properties</value>
</list>
</property>
</bean>

log4j and spring

I am developing a Java desktop application and I am using Spring with it. Now I want to inject log4j to my classes using applicationContext.xml. My log4j properties file is placed in a source folder Resources/log4j.properties
During my search I found out that there are many way to it when its a web application but I found out no help regarding a desktop application.
I am using Apache commons interfaces in my source code and now I want to inject log4j dependency.
Kindly, help me out..
By default, Log4J will simply read its configuration from a "log4j.properties" file in the root of the class path. Since you placed your log4.properties file in the resources source folder, this should work.
If you do not want to store your log4j configuration in your class path then you can use something like this :
<bean id="log4jInitialization"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.util.Log4jConfigurer" />
<property name="targetMethod" value="initLogging" />
<property name="arguments">
<list>
<value>myPropertiesFolder/log4j.xml</value>
</list>
</property>
</bean>

externalizing terracottaconfig property in ehcache.xml file inside Spring framework

There is this tag <terracottaConfig url="host1:9510,host2:9510,host3:9510"/> in ehcache.xml file inside spring web application. I want to externalize url attribute of this tag. Value of URL should be replaced by a property from external file. It will be very helpful if you suggest any solution to this problem.
You can put something like this -
<terracottaConfig url="${terracotta.config.location}" /> , however the big catch is that this will be loaded only from the system properties. It is not resolved from PropertyPlaceHolder as it is not a Spring configuration file.
So if you want to use an external config file, you will basically have to programatically set this system property before the Spring Application starts loading up the ehcache.xml file - one way to do that will be write your custom ServletContextListener to load up your properties file and set the system property based on that, this way when the ehcache.xml is loaded up it would be able to resolve the place holder properly.
Your answer helped me to solve my problem. I just want to add that instead of setting system property through program, I am using util:properties as follows
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" value="#{#systemProperties}"/>
<property name="targetMethod" value="putAll"/>
<property name="arguments">
<util:properties>
<prop key="propertyname_used_in_ecache_xml">#{proerties_defined_using_property_factory['propertyname_defined_in_external_properties_file']}</prop>
</util:properties>
</property>
</bean>
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" depends-on="sysProperties">
<property name="configLocation">
<value>classpath:ehcache.xml</value>
</property>
</bean>

Categories

Resources