Switching between property files dynamically by changing environment name in Spring - java

I was wondering if there is any way that we can set the value of environment variable dynamically without restarting the server so that different property files might get accessed based on the value of currently set environment.
Consider these are my two property files:
config-dev.properties
config-prod.properties
Now since I have appended the name of environment with every file, so I want to know that is it possible that I dynamically change or set the value of environment name and the corresponding property file will be used without restarting the server.
I know how to set the env.name in configuration XML file.
<context:property-placeholder location="classpath:/config-${env.name}.properties>
I want to change the environment name programmatically so the correct property file can be used when it is accessed.

<context:property-placeholder location="classpath:/config-${env.name}.properties> is one way to do it. where your env.name is the run configuration can be the startup parameter you set.
Another way to do it is to use the Spring bean Profile. where you define a profile and the beans defined for those profile would be loaded during the Spring container startup.
<beans profile="dev">
<bean .... />
<context:property-placeholder
location="classpath:conf/properties/dev.properties" />
</beans>
<beans profile="prod">
<bean .... />
<context:property-placeholder
location="classpath:conf/properties/prod.properties" />
</beans>
I am not sure about changing it without restarting the server. since your Spring container has already started, and the beans are already loaded. now you do want to load a different set of beans without restarting the Spring container. I am not sure about that.
The basic reason for that according to me would be upon, how do you change the already autowired dependencies during runtime without affecting any other running application classes? What about a functionality which is being executed and you want to change the DB URL through the switch in the properties file? How do you control that?

Related

Get Spring Environment as Properties

I wonder if there is a way to extract properties from Spring Environment (e.g. obtained from ApplicationContext) in the form of Properties instance? Or, at least, is there a way to enumerate the properties in Spring Environment, or get them all as a map, or any other way I can turn a [initially unknown] set of properties into a Properties object?
I need this in order to create a jclouds Context by calling org.jclouds.ContextBuilder.newBuilder() and .overrides(Properties). The idea is to configure the actual cloud provider solely by means of .properties file, and I don't want to couple application logic with provider-specific properties.
[UPDATE]
The .properties files to be used are configured using <context:property-placeholder>, and it actually specifies a list of paths, like this:
< context:property-placeholder location=
"classpath:/jdbc.properties,
file:${jboss.server.config.dir}/jdbc.properties,
file:${catalina.home}/conf/jdbc.properties"
ignore-resource-not-found="true"/>
which suggests that the .properties file is searched in the mentioned list of locations in order. I would like to achieve the following:
keep the list of .properties files and their possible locations in this XML definition file only;
allow to place jclouds related properties in any of the .properties files mentioned in the XML;
access the properties, resolved and loaded by Spring, in the form of Properties object so I am able to feed that to jclouds ContextBuilder.
Please let me know if all of this is feasible. Thank you in advance!
-Vlad
If you wan't to use properties in your Spring configuration then you can simply use:
<context:property-placeholder location="classpath:foo.properties" />
To get the properties in your code later you can simply read this file from the classpath into a Properties object:
props.load(MyClass.class.getClassLoader().getResourceAsStream("foo.properties"));
Alternatively you can have a look at PropertyPlaceholderConfigurer.
UPDATE
Updated after Deinum's remark but only if you are getting the properties from a Spring managed bean:
<util:properties id="myProps"
location="classpath:foo.properties"/>
<context:property-placeholder properties-ref="myProps" />
Now you can inject myProps into Spring managed beans (no need to load them again from the classpath).
You could use PropertiesFactoryBean and do something like this:
<bean id="jcloudsProps"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>your/props/file.properties</value>
</property>
</bean>
You can then use jcloudsProps as you would any other Spring bean.

Working with properties files outside war with Spring

I am working on a Spring 3.0.5 web application that accesses LDAP and two databases. I have a properties with configuration information for the LDAP server and that databases, in applicationContext-security.xml and dispatcher-servlet.xml, but I would like to make it so each server can have different data properties without changing a file in the WAR. Can I somehow put a file somewhere else on the server and still access it from within my application?
Add this to your context
<context:property-placeholder location="${envfile}"/>
This will load the properties file located at ${envfile}, a variable you can set with Java's startup paramater like this
-Denvfile="file:/var/server/environment.properties"
Or maybe in Tomcat's startup script
CATALINA_OPTS=" -Denvfile=file:/var/server/environment.properties"
Values can be retrieved in your controllers using Springs Value annotation like this:
#Values("${myvalue}")
private String myValue;
Please note that these features require Spring 3.1, more information here
Good luck!
Try
<util:properties id="props" location="file:///path/to/server.properties"/>

Spring MVC putting values into XML Config file

I am working a Spring MVC project and in my Service object I need some information like system password, id, url etc but I would like to put this into one of the XML files so it can be changes without changing code.. which XML should I put it in and how do I read it into the object
Moving constants to XML is a first step, but to make your application truly configurable you should use external .properties file:
<context:property-placeholder location="file:///foo/bar/conf.properties" />
And then use it everywhere in your XML configuration:
<property name="password" value="${db_password}"/>
Where conf.properties contains:
db_password=secret
Note that you can also place properties file inside WAR (with location="classpath:/foo/bar/conf.properties").
If you are a happy user of Spring 3.1 (currently RC2) you can take advantage of new #PropertySourceannotation:
#Configuration
#PropertySource("classpath:/com/myco/app.properties")

Setting up connection time out using configuration

I realized that I haven't set the time out for the JDBCTemplate using the setQueryTimeOut method. My code is in production as I would ideally want a solution to set the timeout from some configuration instead of recompiling the code. Is there a way to set the query time out via say the data source configuration or any other property outside the Java.
I tried via the accepted solution to this post. Didn't work for me. I get org.springframework.beans.NotWritablePropertyException: Invalid property 'connectionProperties' of bean class
You can use the queryTimeout field with configuration:
In your JDBCTempalte xml - <property name="queryTimeout" value="${query.timeout} />
Use a PropertyPlaceholderConfigurer to load properties from a .properties file on the classpath. The easiest way is through <context:property-placeholder location=".." />
Add the query.timeout=x in your .properties files

Spring JMX. Set the default value of #ManagedAtrribute through XML

I'm using Spring 3.0.5
I have a #ManagedResource bean, for some of the #ManagedAttribute methods which I want to set a defaultValue. Instead of setting it to a hardcoded value I want to be able to read it from a property value at load time, since the default changes from environment to environment.
A snippet from my programs applicationContext.xml:
<context:mbean-export default-domain="sampleApp"/>
<bean id="managedBean" class="com.example.sampleBean">
<constructor-arg value="Sample Bean"/>
<constructor-arg value="${sample.property}"/>
</bean>
I believe I have to use the XML configuration to be able to do this, but haven't figured out how to do it yet.
You can add the following to your applicationContext.xml, it should expose the properties you are after:
<context:property-placeholder location="classpath:application.properties"/>
So if the application.properties file you are pointing to above contains a property called sample.property then Spring will use that to inject into your ${sample.property} placeholder.
For more details you can see the Spring reference here.

Categories

Resources