You can build a main
Maven project which has three submodules, say master
, platform
and parent
.
(Note: for all the following projects you should set GAV parameters consistently with your application architecture, in order to have significant names easy to understand)
The main
project has simply the order in which the other projects will be evaluated by Maven:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme.projects</groupId>
<artifactId>main</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
....
</plugin>
</plugins>
</build>
<modules>
<module>master</module>
<module>parent</module>
<module>platform</module>
</modules>
The master
pom contains the list of project to be built and their order (aka Reactor order)
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme.projects</groupId>
<artifactId>master</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../../P1</module>
<module>../../P2</module>
</modules>
</project>
As you can see P2 must be inserted after P1, since P2 has P1 as a dependency.
The platform
pom contains all information about your platform, like JDK version, maven plugin versions, encoding and so on.
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme.projects</groupId>
<artifactId>platform</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.2</version>
</plugin>
<plugin>
.....
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
The parent
pom has the platform pom as a parent and contains all global GAV information about the dependencies you are going to use in your project (Spring, CXF, junit, log4j etc.)
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.acme.projects</groupId>
<artifactId>platform</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../platform</relativePath>
</parent>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<groupId>com.acme.projects</groupId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.1.6.RELEASE</spring.version>
<!-- == Web Services == -->
<cxf.version>3.0.4</cxf.version>
<!-- == Testing == -->
<junit.version>4.12</junit.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- == LOGGING == -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- == SPRING == -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Finally you will have a project structure like this:
and you will have to put the right pom inside each project folder.
Now, both P1 and P2 projects must have parent
project as parent, and moreover P2 must have a dependency to P1.
In order to have the whole reactor built, you have only to set yourself into the main
directory and use the command
mvn clean install
which will compile your P1 project and make it available as a dependency for your P2 project.
This approach has many advantages:
- you can add more projects to your list and have them automatically compiled without worrying about placing jars around (every new project must have
parent
as parent)
- make easier to automate the process with CI tools like Jenkins, to have compiling process under control
- concentrate dependencies version at the top of your hierarchy and specialize in a subproject as needed