<context:load-time-weaver/> dynamically - spring

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.

Related

spring trying to load environment variable

I have a question about trying to inject an environment variable into my spring mvc controller.
I have an environment variable as follows...
POS_MANAGER_SERVER_REPORTING=myserver
In my spring application context I have ...
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE"
p:searchSystemEnvironment="true"/>
<bean name="posManagerController"
class="com.mycompany.reporting.controller.PosManagerController"
p:posManagerServer="${POS_MANAGER_SERVER_REPORTING}" />
When I do not define the system variable in websphere the application does not start up properly. When I add the variable it does. But for some reason the value being injected into my controller is null.
Can someone help me with what might be going wrong here? i.e. Why the environment variable is not loaded properly?
Just to give you some more information, the Controller is loaded in the child context (-servlet.xml) using the #Controller annotation but in the parent context (applicationContext.xml) I also have the controller defined as appeared above. My understanding is that spring is smart enough to be able to handle this. I've listed this information just in case this might be the cause of the issue.
thanks
Quote from documentation:
Also, BeanFactoryPostProcessors are scoped per-container. This is only relevant if you are using container hierarchies. If you define a BeanFactoryPostProcessor in one container, it will only be applied to the bean definitions in that container. Bean definitions in one container will not be post-processed by BeanFactoryPostProcessors in another container, even if both containers are part of the same hierarchy.
So, you need a PropertyPlaceholderConfigurer in -servlet.xml file to make it work.

Alternative to spring profiles

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.

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.

Dealing with two different values of a property (cloud and default) in cloudfoundry and the #Value annotation

I am in reference to Spring's #Value annotation as documented here: #Value and Spring profiles.
I need to be able to have different values for a given property such as:
websiteContext=http://localhost:8080/kadjoukor
...according to whether the app is running locally or on the cloud. I am not sure how to achieve that with the #Value("${websiteContext}") annotation...
What is the best practice for dealing with such an issue?
If you are using Spring 3.1 or later, you can take advantage of bean profiles and the CloudFoundry "cloud" profile to load a different properties file depending on the environment. That might look something like this in a Spring XML configuration file:
<beans profile="default">
<context:property-placeholder location="default.properties"/>
</beans>
<beans profile="cloud">
<context:property-placeholder location="cloud.properties"/>
</beans>
Here are a few good blog posts that explain how this works in more detail:
SPRING 3.1 M1: UNIFIED PROPERTY MANAGEMENT
USING CLOUD FOUNDRY SERVICES WITH SPRING: PART 4 – SPRING PROFILES

<context:property-placeholder> properties not accessible to the child (web) context

A typical use-case: I'm having applicationContext.xml and dispatcher-servlet.xml. In the parent context (applicationContext.xml) I have:
<context:property-placeholder location="classpath:application.properties" />
However, the properties loaded by it are not accessible to the web context - neither in xml, nor using #Value. (They are just not resolved and the expression (${varName}) is set as value instead)
I worked it around by adding the <context:property-placeholder> to dispatcher-servlet.xml as well, but I wondered whether:
This is expected behaviour
There isn't a better way to expose the properties to the child context.
Yes, this is an expected behaviour. <context:property-placeholder> creates a BeanFactoryPostProcessor which is applied at per-context basis. So, you'll need a postprocessor in the child context anyway.

Resources