I'm looking at restructuring a large Maven project...
A basic overview of our current structure:
build [MVN plugins, third party dependency management]:5.1
NRW Utils:6.0.0.0-beta12-SNAPSHOT
server-utils:6.0.0.0-beta12-SNAPSHOT
...
CMW Root:6.0.0.0-beta12-SNAPSHOT
cmw-webapp:6.0.0.0-beta12-SNAPSHOT
cmw-core [dependencies on NRW Utils]:6.0.0.0-beta12-SNAPSHOT
...
NRW Root :6.0.0.0-beta12-SNAPSHOT
nrw-webapp [depends on NRW Utils & CMW Root modules]:6.0.0.0-beta12-SNAPSHOT
...
The reason for change:
The size of each collective module (i.e. NRW Utils, CMW Root and NRW Root) is getting larger and the build process is beginning to take an unbearable amount of time (~4hrs sometimes).
The new plan:
build [MVN plugins, third party dependency management]:5.1
NRW Utils:6.0.0.0-NU-beta4-SNAPSHOT
server-utils:6.0.0.0-NU-beta4-SNAPSHOT
...
CMW Root:6.0.0.0-CMW-beta12-SNAPSHOT
cmw-webapp:6.0.0.0-CMW-beta12-SNAPSHOT
cmw-core [dependencies on NRW Utils]:6.0.0.0-CMW-beta12-SNAPSHOT
...
NRW Root :6.0.0.0-NRW-beta9-SNAPSHOT
nrw-webapp [depends on NRW Utils & CMW Root modules]:6.0.0.0-NRW-beta9-SNAPSHOT
...
We have started introducing 'keys' in the version to distinguish between different 'collective modules' and hence can easily perform stepped releases. In addition, our utility modules are far more stable so we may not require nearly as many beta releases - there is now no restriction on keeping beta numbers in sync.
It is also worth noting that there are in fact 5 different 'collective modules' (not just 3) all to be built with different versions (distinguished by unique keys) which is why I thought it'd be nice to have a centralised place for versions, as opposed to duplicate properties in 5 different POMs.
The problem now lies in the contents of POM files when defining dependencies on modules in a different 'collective module' of a different version.
The proposed solution to dependency version management:
build [MVN plugins, third party dependency management]:5.1
nrw-version-management:6.0.0.0-beta-SNAPSHOT
[contains properties defining latest versions of each collective module]
NRW Utils:6.0.0.0-NU-beta4-SNAPSHOT
server-utils:6.0.0.0-NU-beta4-SNAPSHOT
...
CMW Root:6.0.0.0-CMW-beta12-SNAPSHOT
cmw-webapp:6.0.0.0-CMW-beta12-SNAPSHOT
cmw-core [dependencies on NRW Utils]:6.0.0.0-CMW-beta12-SNAPSHOT
...
NRW Root :6.0.0.0-NRW-beta9-SNAPSHOT
nrw-webapp [depends on NRW Utils & CMW Root modules]:6.0.0.0-NRW-beta9-SNAPSHOT
...
nrw-version-management (pom.xml):
...
<parent>
<groupId>com.project</groupId>
<artifactId>build</artifactId>
<version>5.1</version>
</parent>
<groupId>com.project</groupId>
<artifactId>nrw-versions-manager</artifactId>
<version>6.0.0.0-beta-SNAPSHOT</version>
<name>Version Maven Properties</name>
<description>A centralised place for all module property versions</description>
<packaging>pom</packaging>
<properties>
<nrw.utilities.version>6.0.0.0-NU-beta4-SNAPSHOT</nrw.utilities.version>
<nrw.cmw.version>6.0.0.0-CMW-beta12-SNAPSHOT</nrw.cmw.version>
<nrw.version>6.0.0.0-NRW-beta9-SNAPSHOT</nrw.version>
</properties>
...
CMW Root (pom.xml):
...
<parent>
<groupId>com.project</groupId>
<artifactId>nrw-versions-manager</artifactId>
<version>${nrw.core.version}</version>
...
</parent>
<groupId>com.project</groupId>
<artifactId>CMW-root</artifactId>
<version>6.0.0.0-CMW-beta12-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>server-utils</artifactId>
<version>${nrw.utilities.version}</version>
</dependency>
...
</dependencyManagement>
<profiles>
<profile>
<id>all</id>
<modules>
<module>cmw-webapp</module>
<module>cmw-core</module>
...
</modules>
</profile>
...
</profiles>
...
N.B. the property ${nrw.core.version} would then be set to 6.3.0.0-beta-SNAPSHOT for a snapshot build via command line arguments (or a default property value).
A possible release process (for 6.0.0.0):
- Build the 5.1 build module if not already built
- Build nrw-version-management 6.0.0.0 (to avoid snapshot dependencies - however no properties are changed yet)
- Build NRW Utils 6.0.0.0-NU cmd args: -Dnrw.core.version=6.0.0.0
- Build CMW Root 6.0.0.0-CMW cmd args: -Dnrw.core.version=6.0.0.0 -Dnrw.utilities.version=6.0.0.0-NU
- Build NRW Root 6.0.0.0-NRW cmd args: -Dnrw.core.version=6.0.0.0 -Dnrw.utilities.version=6.0.0.0-NU -Dnrw.cmw.version=6.0.0.0-CMW
- Re-build nrw-version-management 6.0.0.0 for repository cmd args: -Dnrw.core.version=6.0.0.0 -Dnrw.utilities.version=6.0.0.0-NU -Dnrw.cmw.version=6.0.0.0-CMW
- Build nrw-version-management 6.1.0.0-beta-SNAPSHOT with new dev versions and update POM file
The problem:
The build process seems long-winded, especially related to the nrw-version-management module. Also, I started seeing this warning:
'version' contains an expression but should be a constant
And having done some investigating I now understand expressions are not recommended when setting versions (when specifying a parent POM):
- Warning on using project.parent.version as the version of a module in Maven 3
- Maven: property substitution not done for /project/version tag of pom?
- http://maven.40175.n5.nabble.com/Pom-Parent-Version-Properties-td124576.html
The questions:
- Can I just ignore this warning? Some posts are starting suggest that it might just be acceptable to specify parent POM versions using properties.
- Is this general approach conventional? Or flawed?
- Are there better solutions to address the re-structuring of this growing project?
Thanks in advance.