Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven advice relating to versioning of a large project and the avoidance of versions containing expressions

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):

  1. Build the 5.1 build module if not already built
  2. Build nrw-version-management 6.0.0.0 (to avoid snapshot dependencies - however no properties are changed yet)
  3. Build NRW Utils 6.0.0.0-NU cmd args: -Dnrw.core.version=6.0.0.0
  4. 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
  5. 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
  6. 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
  7. 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.

like image 849
Ed . Avatar asked Oct 09 '22 23:10

Ed .


1 Answers

The benefits of having one single version for all sub modules is simplicity, a benefit that shouldn't be under estimated.

You should indeed ask yourself several times if you really want to depend on different versions of modules in the same hierarchy. As you pointed out release becomes cumbersome.

By handling relationships in a standardized way with single version and deploying to your local repo after successfull builds you should be able to enjoy dependency management the way it was intended.

If you restructure your project so that it adheres to the conventions of the release plugin, release becomes a breeze.

like image 62
obr Avatar answered Oct 12 '22 11:10

obr