How do I control spring injections that vary between the test environment and the production environment?

为君一笑 提交于 2019-12-01 06:20:21

Spring itself has support for profiles (if you're using 3.1 or newer), for a web-application you can use context-parameter to set the active profile for different environments in the web.xml:

<context-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>test</param-value>
</context-param>

Edit: For Maven & Jenkins, you should be able to set the parameter for a build job as follows:

First, let Maven filter your xml-resources (in this example, only files ending with xml are filtered, others are included without filtering) by adding the following into your pom.xml inside the <build> </build> -tags:

    <resources>
        <resource>
            <directory>src/main/webapp</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/*xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/webapp</directory>
            <filtering>false</filtering>
            <excludes>
                <exclude>**/*xml</exclude>
            </excludes>
        </resource>
    </resources> 

Then, parameterize the context-param in your web.xml:

<context-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>${env.SPRINGPROFILE}</param-value>
</context-param>

Then parameterize the build job in Jenkins to set the desired string parameter for SPRINGPROFILE (for example test or prod): https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Build

chad

It's probably a bad idea to do anything with the build of the web app artifact ( Maven best practice for generating artifacts for multiple environments [prod, test, dev] with CI/Hudson support? ). While you could use various mechanisms to produce a WAR file with different configurations of the Spring injections for different contexts, the WAR artifact should be the same every time it's built.

In order to extract the configuration out of the WAR, I have used Spring 3's ability to pull in override values from an external property file. I define default, i.e. produciton, values of my business objects. And I configure spring to check for the existence of a properties file, something I will deploy when the app is in a testing environment and requires mock injections. If that properties file exists, it's values are injected instead. Here's the relevent bit of the spring config file.

<!-- These are the default values -->
    <util:properties id="defaultBeanClasses">
    <prop key="myManagerA">com.myco.ManagerAImpl</prop>
    <prop key="myManagerB">com.myco.ManagerBImpl</prop>
</util:properties>

<!-- Pull in the mock overrides if they exist. -->
<context:property-placeholder 
    location="file:///my/location/mockBeans.properties"
    ignore-resource-not-found="true"
    properties-ref="defaultBeanClasses"/>

<!-- The beans themselves. -->  
<bean id="managerA" class="${myManagerA}"/>
<bean id="managerB" class="${myManagerB}"/>

And here is the contents of the external "mockBeans.properties" file:

#Define mock implementations for core managers
myManagerA=com.myco.ManagerAMockImpl
myManagerB=com.myco.ManagerBMockImpl

This works nicely. You can even include the mockBeans.properties file in the actual WAR, if you like, but not in the live location. Then the test environment task would be too move it to the location pointed at by the spring config. Alternatively, you could have the mock properties reside in a completely different project.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!