Sunday, 28 September 2014

Maven Multiple Environment Build and Set Up

One of the fundamental requirements of a build process is that it must be possible to use different configuration for binaries, which are used in different environments. If you are using Maven, it is possible to fulfill this requirement by using build profiles. 

This can be done either by using maven ant-run plugin as shown here. But a more robust and maven specific way of doing is to have a separate profile  for development, testing and production purposes.Each profile must have its own configuration file. 


These requirements can be fulfilled by following these steps:

  • Creating profile directories and profile specific configuration files.
  • Adding build profile configuration to the POM file.

These steps are described with more details in following Sections.

Creating Profile Specific Configuration Files

First, I created profiles directory under the project’s resources directory. After that was done I created 3 config files for dev,prod and test environment. Here's the project structure:







Adding the Build Profile Configuration To Pom.xml

Second,add the build profile configuration to the POM file. The profile configuration section of the POM file is given (with comments highlighted) below:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 
 <modelVersion>4.0.0</modelVersion>
  <groupId>com.test</groupId>
  <artifactId>DemoWebApp</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>DemoWebApp Maven Webapp</name>
  <url>http://maven.apache.org</url>
<!-- Profiles configuration -->

<profiles>
    <profile>
        <id>dev</id>
       <!-- Dev profile is active by default -->
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
       <properties>
            <!--
                Specifies the build profile id, which is used to find out the correct properties file.
                This is not actually necessary for this example, but it can be used for other purposes.
            -->
            <env>dev</env>
        </properties>

        <build>
           <filters>
               <!--
                    Specifies path to the properties file, which contains profile specific
                    configuration.
               -->
                <filter>src/main/resources/profiles/config-${env}.properties</filter>
            </filters>
            <resources>
                <!--
                    Placeholders found from files located in the configured resource directories are replaced
                    with values found from the profile specific configuration files.
                -->
                <resource>
                    <filtering>true</filtering>
                    <directory>src/main/resources</directory>
                   <!--
                        You can also include only specific files found from the configured directory or
                       exclude files. 
                   -->
                    <!--
                    <includes>
                        <include></include>
                    </includes>
                    <excludes>
                        <exclude></exclude>
                    </excludes>
                    -->
               </resource>
            </resources>
        </build>
    </profile>
    <profile>

        <id>test</id>

        <properties>
            <!--
                Specifies the build profile id, which is used to find out the correct properties file.
                This is not actually necessary for this example, but it can be used for other purposes.
            -->
            <env>test</env>
        </properties>

        <build>
           <filters>
               <!--
                    Specifies path to the properties file, which contains profile specific
                    configuration.
               -->
                <filter>src/main/resources/profiles/config-${env}.properties</filter>
            </filters>
            <resources>
                <!--
                    Placeholders found from files located in the configured resource directories are replaced
                    with values found from the profile specific configuration files.
                -->
                <resource>
                    <filtering>true</filtering>
                    <directory>src/main/resources</directory>
                   <!--
                        You can also include only specific files found from the configured directory or
                       exclude files. 
                   -->
                    <!--
                    <includes>
                        <include></include>
                    </includes>
                    <excludes>
                        <exclude></exclude>
                    </excludes>
                    -->
               </resource>
            </resources>
        </build>
    </profile>
    <profile>

        <id>prod</id>

        <properties>
            <!--
                Specifies the build profile id, which is used to find out the correct properties file.
                This is not actually necessary for this example, but it can be used for other purposes.
            -->
            <env>prod</env>
        </properties>

        <build>
           <filters>
               <!--
                    Specifies path to the properties file, which contains profile specific
                    configuration.
               -->
                <filter>src/main/resources/profiles/config-${env}.properties</filter>
            </filters>
            <resources>
                <!--
                    Placeholders found from files located in the configured resource directories are replaced
                    with values found from the profile specific configuration files.
                -->
                <resource>
                    <filtering>true</filtering>
                    <directory>src/main/resources</directory>
                   <!--
                        You can also include only specific files found from the configured directory or
                       exclude files. 
                   -->
                    <!--
                    <includes>
                        <include></include>
                    </includes>
                    <excludes>
                        <exclude></exclude>
                    </excludes>
                    -->
               </resource>
            </resources>
        </build>
    </profile>

</profiles>
</project>


Now we have created the needed profile specific configuration files and configured Maven to use them. As explained  earlier, the configuration file contain only one property called jdbc.url, which specifies the database url . Now this value will be used in spring-bean.xml file during maven build based on profile you pass.

Note: Spring dependency are not included in the pom.The tutorial just focus on demonstrating multi environment project set up with Maven.

Here's the content of different config files:

config-dev.properties
jdbc.url=jdbc:dev

config-prod.properties
jdbc.url=jdbc:prod

config-test.properties
jdbc.url=jdbc:test

Maven Before processing (spring-bean.xml):

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="url" value="${jdbc.url}"/>
</bean>

Now build your project based on your requirement for different environment (for example prod):

mvn clean package -P prod

Maven after processing (spring-bean.xml)


<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="url" value="jdbc:prod" />
</bean>

I hope this tutorial was informative. There does not seem to be too much information on how to do this sort of thing multiple environment build with Maven, perhaps because this process is not standard and teams and organizations have evolved different strategies to deal with this problem. 

Reference:
http://maven.apache.org/guides/mini/guide-building-for-different-environments.html
http://maven.apache.org/guides/introduction/introduction-to-profiles.html

No comments:

Post a Comment