1

for my spring-mvc application I created several types of configuration (unittest, integration, qa, production). All the configs are in one war-file, so there is only one type of application I create. Which configuration to take should be decided by the server, where the application is running.

To decide what kind of configuration should be used, I have to look into a file. After that I can decide which configuration should be used by spring mvc.

For now by convention there is always the -servlet.xml used. Is there a way how to decide dynamically which config to take?

Regards, Michael

axtavt
  • 239,438
  • 41
  • 511
  • 482
mibutec
  • 2,929
  • 6
  • 27
  • 39
  • there is a planned feature about multiple configurations for the next release of spring. – Bozho Jan 16 '11 at 14:57
  • The more general question behind this is actually: How to deal with configuration for multiple environments in a Spring application? – Axel Fontaine Jan 16 '11 at 15:10

3 Answers3

4

Here is a solution that I use. It works very well:

  • Put the configuration differences in property files.
  • Keep a single Spring xml with placeholders.
  • Use PropertyPlaceholderConfigurer to set the properties.
  • PropertyPlaceholderConfigurer can use system properties to resolve the name of the property file to load.
  • Set a system property with the name of your environment before initilizing the PropertyPlaceholderConfigurer (you can do this in a bean that reads the value out of your file).

And there you go! The environment will be cleanly detected, and the relevant properties will be loaded!

No need to wait for Spring 3.1, you can use this solution today with 3.0.

Axel Fontaine
  • 34,542
  • 16
  • 106
  • 137
  • Hi Axel, thanks for your fast reply. As far as I know with PropertyPlaceholderConfigurer can just configure propertys. But I also want to configure beans (inmemory-db instead real-db). – mibutec Jan 16 '11 at 15:10
  • It still works. Use a property for the name of the bean you depend on. If you have many references, you can use an alias with a property for the name of the bean it points to. – Axel Fontaine Jan 16 '11 at 15:12
  • If you mark the beans as lazy-init=true, only the ones used in the current environment will be initialized. – Axel Fontaine Jan 16 '11 at 15:13
  • See here for an elegant way to load the proerty files per env: http://stackoverflow.com/questions/1311360/property-placeholder-location-from-another-property/1312341#1312341 – Pablojim Jan 16 '11 at 17:17
  • @Pablojim Yes, that's exactly how I see it. – Axel Fontaine Jan 16 '11 at 17:32
0

I have the same setup, but I use maven to build the WARs differently. I use a PropertyPlaceholderConfigurer in the context:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

   <context:property-placeholder location="classpath:datasource.properties" ignore-unresolvable="true" />

   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="${jdbc.driver}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}" />

   <!--other beans-->
</beans>

then I setup an environments folder:

src
--main
----environments
------dev
--------datasource.properties
------cert
--------datasource.properties
------prod
--------datasource.properties

Then in my Maven pom, I use a build profile to copy anything in the environment folder based on a parameter flag in the maven command:

<profiles>
        <profile>
            <id>environment</id>
            <activation>
                <property>
                    <name>environment</name>
                </property>
            </activation>
            <build>
                <resources>
                    <resource>
                        <directory>
                            src/main/environments/${environment}
                        </directory>
                    </resource>
                </resources>
                <!-- other build config and plugins -->

so the following command:

mvn clean -Denvironment=dev install

would copy the dev datasource.properties to the war

hisdrewness
  • 7,599
  • 2
  • 21
  • 28
  • That was my first plan. But I'm goinig to store my application to a vm-image and deploy that image to my servers. So I need my application to work as every kind of instance – mibutec Jan 16 '11 at 17:11
  • Building a different artifact for each environment is a little nasty - see my answer here to allow dynamic loading of properties per env: http://stackoverflow.com/questions/1311360/property-placeholder-location-from-another-property/1312341#1312341 – Pablojim Jan 16 '11 at 17:16
  • 1
    I'm with Pablojim on this. Artifact/environment is an (unfortunately widespread) anti-pattern. It undermines the credibility of testing, as you basically deploy a different artifact into production as the one you tested. – Axel Fontaine Jan 16 '11 at 17:44
0

After all I'm using PropertyPlaceholderConfigurer but slightly differnt than Axel mentioned: I load just one property from my configuration and use it to determine which import to use. Because of https://jira.springframework.org/browse/SPR-1332 I cant use a file to store the instance-type, but have to use environment-variables.

<bean id="propertyConfigurerOne" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<import resource="classpath:/web${vabse.Environment}.xml"/>
mibutec
  • 2,929
  • 6
  • 27
  • 39
  • This is certainly a valid way (and much better than the widespread artifact/environment anti-pattern). As I described in my answer, you can still use a file if you read its value into a system property. (I use this exact solution with my current client) – Axel Fontaine Jan 16 '11 at 17:39
  • The reason I prefer the property approach, instead of the import one you have here, is that I want make sure the wiring of my beans is as similar as possible on all environments in order to increase the effectiveness of testing and avoid surprises in production. – Axel Fontaine Jan 16 '11 at 17:42