Java – Spring 3.1 bean visibility using bean definition profiles

applicationcontextjavamavenspring

I have been experimenting with using Spring 3.1's bean definition profiles and nested beans. I had hoped that I could define different beans depending on the active profile. Consider the following heavily over simplified example such that my Spring context contains something like

<bean id="say" class="test.Say" p:hello-ref="hello"/>

<beans profile="prod">
    <bean id="hello" class="test.Hello" p:subject="Production!"/>
</beans>

<beans profile="dev">
    <bean id="hello" class="test.Hello" p:subject="Development!"/>
</beans>

I get the following error:

Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'say' defined in class path resource
[applicationContext.xml]: Cannot resolve reference to bean 'hello'
while setting bean property 'hello'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'hello' is defined at
org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at
org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
aJava Result: 1

I was expecting that the hello bean would be defined according to the active Maven profile (in my case prod or dev). I'm starting to think that the Spring active profiles (spring.profiles.active) may be completely unrelated to Maven profiles.

Could somebody please explain where I am going wrong? (Is this even possible using profiles?).

Best Answer

I was expecting that the hello bean would be defined according to the active Maven profile (in my case prod or dev). I'm starting to think that the Spring active profiles (spring.profiles.active) may be completely unrelated to Maven profiles.

That's true, they are unrelated.

Here is how you can fix it:

Make sure that the web.xml that you have in src/main/webapp/WEB-INF/ folder has the following context setting:

<context-param>
    <param-name>spring.profile.active</param-name>
    <param-value>${profileName}</param-value>
</context-param>

And then make sure that the maven-war-plugin has filtering turned on for the web.xml:

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
    </configuration>
</plugin>

And then lastly in your profiles:

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <profileName>dev</profileName>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <profileName>prod</profileName>
        </properties>
    </profile>
</profiles>

You could also add a default value in the normal properties section:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <profileName>dev</profileName>
</properties>

So if you run without the -P option the dev spring profile will be used.

When running mvn package the web.xml will have the correct value for the spring.profile.active.

Related Topic