Alternative to spring profiles - spring

Using spring 3 I can determine which bean to use at runtime. But using Spring 2.5 what is the alternative?
Here is the config within my context file :
<jee:jndi-lookup id="myDataSource" jndi-name="jdbc/mydb"
resource-ref="true" expected-type="javax.sql.DataSource" />
I can use a profile to determine whether or not to use this datasource, what is the alternative when using an earlier version of spring (earlier than Spring 3)
Update :
"myDataSource" will be injected when I run my app locally, on a prod environment the "jndi" lookup, will be used. To inject "myDataSource" using Spring 3 I can use "profiles" but what alternative can I use if not using Spring 3 ?

You could define all your environment depend beans into several files, such as :
beans-dev.xml
beans-prod.xml
Your XML config would be :
<beans>
<import resource="beans-${myapp.env}.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
In this case, myapp.env property is a JVM system property, i.e. configured with -Dmyapp.env=dev or -Dmyapp.env=prod. myapp.env cannot be setted from a property placeholder since Spring <import> are resolved before property placeholders.

You need to build out this kind of thing yourself. Typically by maintaining a number of different files for each profile that get composed together and a convention for picking the correct file at runtime. A -D System Property can help you pick which one. For example, we could have applicationContext-dev.xml and applicationContext-prod.xml, our applicationContext.xml would import applicationContext-${activeProfile}.xml, and you can set and load -DactiveProfile=dev; you can infer some of the other conventions like a context-param in the web.xml, etc. from how Spring3 profiles are designed.

Related

How can I inject Spring parameters based on Maven profile

I would like to inject Spring environment-based values (such as URL's for dev, stage, prod) into my Spring xml, based on Maven profiles.
I see a few related questions like this on DI using Maven and this on switching environments but I am not seeing a specific example of how to inject an environment-based value based on the Maven profile.
Can someone please guide me.
It sounds like you just need to use PropertyPlaceholderConfigurer:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
</bean>
<bean id="greetings" class="Greeting">
<property name="message" value="${greeting}" />
</bean>
Which would inject the greeting system property into your bean. Then your Maven profiles can define system properties which would be injected.
Depending on what version of Spring you're using (although it sounds like an older one, given your XML bean definitions), I would be tempted to use the Maven profile to select a Spring profile. For example, you can define -Dspring.profiles.active=dev and put your config in application-dev.properties.

Changing Properties values in Spring MVC

I am trying to load dynamic values from properties file into a Bean Class (Spring MVC project).
I had used following tags to load values.
<context:property-placeholder
location="file:/home/java/examresults/departments.properties"
ignore-unresolvable="true" order="2"/>`
But changing the value in properties file after starting the application, it does not reflected at the form.
I am injecting these values into a class using following declaration.
<bean id="beanmessage" class="examresults.bean.MessageClass" scope="prototype">
<property name="imagelocation" value="/home/java/examresults/"/>
<property name="boards" value="${boardvalue}"/>
<property name="departments" value="${deptvalue}"/>
</bean>
Hence, I am not able to fully utilizing the properties file in my Spring MVC Application.
If you modify the properties file, the webserver needs to be reloaded to make the changes reflected.
When a webserver start, it will instantiate all the registered bean with the configured properties. So if you made changes to the configuration after the webserver started, the bean doesn't know about the changed configuration, because it's already instantiated in the application context / IoC container.
To make the changes in properties files reflected is done by restarting / reloading the webserver (either tomcat or jetty).

Maven resource filtering - Spring application

I'm just wondering, at what point does the Maven resource filtering mechanism inject values from a profile into a target file? I'm asking because my application is using Spring, and depending on a JVM property, it will call one of my apps environment files which is in turn used to supply configuration information to spring beans as they get created.
I would like to move passwords and db type info from the environment file into the Maven Settings.xml file however I'm wondering will Spring overwrite or conflict with the way Maven resource filtering is working?
The goal is for Spring to decide what environment the application is running in and choose an environment file which will have already had the necessary values injected by Maven.
Thanks
Maven replaces placeholders within the process-resources phase. See http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
So when spring starts creating its context the values are there.
You can use the PropertyPlaceholderConfigurer to read a properties file and make them available in the spring context:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file://${config.dir}/external-config.properties</value>
</list>
</property>
</bean>
"config.dir" is in the system properties: java -Dconfig.dir=/dir/ or i think it can be a context parameter as well.
within the spring context ${key} from the properties file can be used to configure beans. Depending on the version of spring also annotations are available. Or there is a namespace for the PropertyResolver too.
So maven filtering and spring work nicely together.

Spring approach for changing configuration source by environment

I'm new to Spring and trying to figure out the best way to handle the following scenario:
We have an application where for local development and testing, all configuration values are pulled from a Properties file. When the app is deployed on to the App Server (Websphere in this case), instead of properties file we use JNDI resource properties.
Is there an accepted way of handling this in Spring? For a non-Spring application I probably would have done something like this using a good ol' factory pattern to decide the config source. For Spring, I've seen examples that use different context XML files per environment (sounds messy), or make use of Spring "Profiles".
Is there a generally accepted practice for this scenario?
Spring profiles are rather new and they were added precisely to address your problems. Moreover they should deprecate all other workarounds like different context XML files you mention.
For the sake of completeness here is an example:
<beans profile="test">
<context:property-placeholder location="/foo/bar/buzz.properties" />
</beans>
<beans profile="prd">
<jee:jndi-lookup id="properties" jndi-name="foo/bar/name"/>
</beans>
Depending on which profile you choose during deployment/startup, only one of the beans above will be instantiated.
Another approach I've never tried but seems to fit your case is default-value attribute in jee namespace:
<jee:jndi-lookup id="properties" jndi-name="foo/bar/name" resource-ref="true"
default-value="classpath:foo.properties"/>
Not sure if this will help you though.
Assuming Spring 3.1, try using profiles like Tomasz suggested, but instead of setting individual JNDI values for production, use
<beans profile="prd">
<context:property-placeholder/>
</beans>
In Spring 3.1, ContextLoaderListener apparently pulls in JNDI props as a PropertySource by default, so with property-placeholder, when you need to access a value you can just use ${some/jndi/name} in applicationContext.xml or a #Value annotation.
To make sure the webapp gets the values from JNDI, add
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>prd</param-value>
</context-param>
to web.xml.
In your tests, set the system property 'spring.profiles.active' to 'test', and you'll get the values from the props file.
one way to go is you use jndi also for local dev and testing. You could define the same jndi name. I don't know what's your testing server, in practice we use jetty, and maven-jetty plugin to test. It is lightweight and can run from your ide.
another way is like what you said in your question. Making use of Spring profile. Then you could declare different transactionManager beans with same id/name. of course they should be in different profiles. At runtime you could decide which profile should be activated, that is, which bean should be used.

<context:load-time-weaver/> dynamically

I am looking for a way to enable aspectJ load time weaving dynamically, say based on whether a JNDI property is true.
Basically, (context:load-time-weaver) have this tag conditionally.
Any quick way to do this?
Have a look at Spring profiles:
<beans profile="production">
<context:load-time-weaver />
</beans>
If the profile name is production, LTW will be enabled. Otherwise the whole inner block is ignored. I am not sure if profile can be set using JNDI variable, but there are multiple other approaches, e.g.: JVM property, environment variable, web context parameter or you can set them programmatically.

Resources