#ActiveProfile and spring.profiles.active - spring

This is a piece of my applicationContext definition to retrieve some properties.
<!-- get some properties -->
<context:property-placeholder
ignore-resource-not-found="false" ignore-unresolvable="false"
location="classpath:/properties/${spring.profiles.active:test}/some.properties"/>
As you can see I letting the spring.profiles.active decide which properties will be read.
My tests are annotated with:
#ActiveProfile("integration")
You guessed it right my spring bean profiles are actually matching the environments in which to deploy/test the application.
Still my location property is getting resolved to "/properties/test/some.properties". Which is of course because the spring.profiles.active doesn't seem to get resolved in this case.
How could I achieve getting the the right properties?

It is because active profiles may be activated by system property (but in case of #ActiveProfiles it works another way).
Just like this:
<beans profile="dev,prod,qa">
<context:property-placeholder location="classpath:some.properties" ignore-unresolvable="true"/>
</beans>
<beans profile="test">
<context:property-placeholder location="classpath:some-test.properties" ignore-unresolvable="true"/>
</beans>
Also, you may try to change
location="classpath:/properties/${spring.profiles.active:test}/some.properties"
to
location="classpath:/properties/${spring.profiles.active}/some.properties"

See ticket: https://jira.springsource.org/browse/SPR-8982#comment-88498
Someone already had made a request for this:
An option to override an #ActiveProfile specified by test in runtime from command line by "-Dspring.profiles.active" or other systemProperty
My comment:
That or it should set the property spring.profiles.active.

Related

Spring placeholder not resolved

I am declaring properties in applicationcontext.xml and passing external.conf as jvm argument. I am able to read the values in properties file without an issue.
<util:properties id="hbaseProperties" location="file:///${external.conf}/props/hbase.properties"></util:properties>
If i add key in property file as below, it fails to resolve the external conf and its getting printed as ${external.conf}/hdfs-site.xml
site_xml = ${external.conf}/hdfs-site.xml
I am not sure why this is not getting resolved. What should be done to make it work.
Add in your applicationcontext.xml following code snippet
<context:property-placeholder location="<pathToYourPropertyFile>/external.conf"/>
For more information about the property placeholder mechanism look at the spring documentation

Can SpEL be used with import statements in spring xml configuration

I am trying to use SpEL in import statement in spring xml configuration.
I am trying to do this
<import resource="classpath*:/'#{'${enable.mass.quote.service:false}'=='true' ? 'massquoting' : 'quoting'}'-beans.xml"/>
but it is not working, any suggestions please
Actually you are right: <import resource> doesn't support SpEL, but it supports property-placeholders:
// Resolve system properties: e.g. "${user.dir}"
location = environment.resolveRequiredPlaceholders(location);
So, for your case it might look like:
<import resource="classpath*:/${enable.mass.quote.service:quoting}-beans.xml"/>
where enable.mass.quote.service should have value massquoting.
If you have more high condition, e.g. enable.mass.quote.service=true, you should rely on Spring Profiles:
<beans profile="service">
<import resource="classpath*:/massquoting-beans.xml"/>
</beans>
<beans profile="nonService">
<import resource="classpath*:/quoting-beans.xml"/>
</beans>
I too came across this requirement and turns out the answer is NO. SpEL or placeholders cannot be used in Spring import statements because the import happens before the placeholders/expressions are evaluated and substituted. Refer here. Spring profiles is the answer just that Spring profiles were floated beginning Spring 3.1.x so when using an older version of Spring one might have to take on the onerous task of writing custom namespaces and their handlers.

Spring Integration - How to create an optional jms:message-driven-channel-adapter?

I'm looking for a way to conditionally set up jms:message-driven-channel-adapter in spring 3.0 & spring integration 2.2.
I would like to have an entry in a property file like: "create.message.driven.channel.adapter=true" for each environment and I would like spring to decide whether to set up the channel or not based solely on the entry from the property file.
Is there a way to accomplish this using only spring xml configuration and a property file?
You can't do it exactly the way you describe. With Spring 3.1, you could do it with Spring Profiles...
<beans>
...
<beans profile="foo">
<jms:message-driven-adapter ... />
</beans>
</beans>
Then run with ... -Dspring.profiles.active=foo.
You could do it with JavaConfig
#Bean
public Object foo() {
// if property set, return an MDA, otherwise a String
}
Or, probably the easiest, so long as you don't explicitly start() the context, you could use
<jms:message-driven-adapter ...
auto-startup="${start.message.driven.channel.adapter}" />
In which case, the bean would be defined, but it just wouldn't be started so it wouldn't even open a JMS connection. You would also need a property placeholder configurer pointed at your properties file.
But, auto-startup only applies to starting on refresh(), an explicit context.start() will still start it.

How to retrieve context parameters in Spring 3.1 xml context

It seems like there's been a few iterations of property support in spring it's hard to tell what's best practice and the manuals are written from the point of view of someone who is familiar with every other iteration. I feel like this should be a simple and common requirement but given how hard it's been please correct me if there's a more idiomatic way.
What I want is to pass an additional properties file to my spring web app based on a context property which the client is setting using a tomcat descriptor like so
<Context path="/foo" reloadable="true">
<Parameter name="foo.config" value="file:${catalina.base}/conf/foo.properties"/>
</Context>
In spring for the live profile I have this
<beans profile="live">
<context:property-placeholder location="classpath:timetabling.live.properties,${timetabling.config}"
ignore-resource-not-found="true" />
</beans>
So I'd assumed this doesn;t work because I'm trying to configure placeholder suppport with a placeholder. If I use a system property however then this works fine. I know that spring 3.1 has baked in support for system and environment properties so I guess my question is how can I augment this support with something context aware before the placeholder is resolved?
--Update--
looking at http://blog.springsource.org/2011/02/15/spring-3-1-m1-unified-property-management/ particularly at footnote 1, I would expect to have a DefaultWebEnvironment which should already have aceess to context init params. Now I am more confused, can someone provide me with a concrete example of context property retrieval? At this point I feel like I've read every javadoc available and they are just not helpful.
<context:property-placeholder /> sets up a PropertyPlaceholderConfigurer which reads from .properties, system properties and environment variables. A Tomcat context.xml however sets up a servlet context init parameter. So what you need is a ServletContextPropertyPlaceholderConfigurer.

Switching spring application context or Impl java classes using maven profiles

I know the question I'm asking must be answered somewhere but I cant find an example on the net with some guidelines.
I wish to swap out the Spring 3.0 bean definition at build and runtime for a common codebase. I'm also using Maven profiles to build different versions of the same code.
Currently my bean def is
<bean id="somebean" class="com.x.SomeImpl" >
I will need to replace and deploy it at some times as
<bean id="somebean" class="com.x.SomeOtherImpl" >
Now the approaches I'm thinking of are
1) Use Maven profiles to switch out the complete applicationContext.xml to some other applicationContextB.xml based on the Maven profile.
2) Use Maven profiles to somehow? replace only the bean id definition for "somebean"
My questions are:
a) How can Option 2 be achieved?
b) These approaches still compile and package both SomeImpl and SomeOtherImpl during build. How can I pick only one and not the other for compliation and packaging into EAR?
I know Spring 3.1 has env profiles for the beans, but presently that's not an option.
You could consider using the maven resources and filtering feature available. You could have placeholders in your context file and a property file per profile holding values. In each profile, you could use a different property file and appropriately have your context file filtered.
Take a look to Maven Build Helper Plugin add-source.
You can combine profiles and Build Helper Plugin (add-source goal) to add the required classes in both cases.
you can import multiple config files to your config like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="applicationContextA.xml"/>
<import resource="applicationContextB"/>
</beans>
For switching you can use Spring profiles.

Resources