Maven: Configuration For Multipe Environments
I have often heard that it is not possible to create a number of artifacts out of a single Maven module with different configurations. An example from the wild is to have a web-app (or whatever app) which should be running in development, test, q&a and production environment. So you need different configurations for the different environments for example the database connection or whatever. At first glance that seems to be a contradiction cause Maven's paradigm is "One Module One Artifact"?
Now let us start with a webapp project (packaging war) where the pom.xml looks more or less lilke the following:
1<project
2 xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
6 <modelVersion>4.0.0</modelVersion>
7
8 <groupId>com.soebes.maven.multiple.artifacts</groupId>
9 <artifactId>solution3</artifactId>
10 <version>0.1.0-SNAPSHOT</version>
11 <packaging>war</packaging>
12 ....
13</project>
If you call Maven on command line via mvn clean package
you will get a war-file within the target folder
which contains your webapp incl. web.xml and your compiled classes etc. The contents of the war file
will be created based on the compiled classes coming from src/main/java
, the
resources src/main/resources
plus src/main/webapp
folder with the supplemental
dependencies which you have defined inside your pom file.
1.
2|-- pom.xml
3`-- src
4 |-- main
5 | |-- java
6 | |-- resources
7 | `-- webapp
Ok. Now let us come to the point to have some kind of configuration for our web application. We put the configuration into the appropriate folders like test, q&a and production which results into the following structure of the project:
1.
2|-- pom.xml
3`-- src
4 |-- main
5 | |-- java
6 | |-- resources
7 | |-- environment
8 | | |-- test
9 | | | `-- database.properties
10 | | |-- qa
11 | | | `-- database.properties
12 | | `-- production
13 | | `-- database.properties
14 | `-- webapp
So we have to create a war file for test, q&a and production. The simplest way to achieve this is by using the
Maven Assembly Plugin
You need to create an assembly descriptor for every environment. Let us start with the test environment
which looks like the following and should be named test.xml and put into src/main/assembly
folder:
1<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
4
5 <id>test</id>
6 <formats>
7 <format>war</format>
8 </formats>
9 <includeBaseDirectory>false</includeBaseDirectory>
10 <dependencySets>
11 <dependencySet>
12 <unpack>true</unpack>
13 <useProjectArtifact>true</useProjectArtifact>
14 </dependencySet>
15 </dependencySets>
16 <fileSets>
17 <fileSet>
18 <outputDirectory>WEB-INF</outputDirectory>
19 <directory>${basedir}/src/main/environment/test/</directory>
20 <includes>
21 <include>**</include>
22 </includes>
23 </fileSet>
24 </fileSets>
25</assembly>
And finally you need a part in your pom file to use the assembly descriptors:
1<plugin>
2 <groupId>org.apache.maven.plugins</groupId>
3 <artifactId>maven-assembly-plugin</artifactId>
4 <executions>
5 <execution>
6 <id>test</id>
7 <phase>package</phase>
8 <goals>
9 <goal>single</goal>
10 </goals>
11 <configuration>
12 <descriptors>
13 <descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
14 </descriptors>
15 </configuration>
16 </execution>
17 <execution>
18 <id>qa</id>
19 <phase>package</phase>
20 <goals>
21 <goal>single</goal>
22 </goals>
23 <configuration>
24 <descriptors>
25 <descriptor>${project.basedir}/src/main/assembly/qa.xml</descriptor>
26 </descriptors>
27 </configuration>
28 </execution>
29 <execution>
30 <id>production</id>
31 <phase>package</phase>
32 <goals>
33 <goal>single</goal>
34 </goals>
35 <configuration>
36 <descriptors>
37 <descriptor>${project.basedir}/src/main/assembly/production.xml</descriptor>
38 </descriptors>
39 </configuration>
40 </execution>
41 </executions>
42</plugin>
Now the result is that by using a simple mvn package
you get in the target folder three
different war files, named like artifactId-version-test.war
, artifactId-version-qa.war
and
artifactId-version-production.war
which are packaged for the different environments.