Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

Easier maintenance of <version> in large projects

Motivation

If you develop a large project with maven, you will typically split your code into various modules organized in a large tree (POM hierarchy). Maven is a great tool to support the development of such project. However there is a major drawback addressed in this toppic:

Every node in your POM hierarchy has a pom.xml with a groupId, artifactId and a version. Besides you have references to other POMs (or artifacts - however you see it) in your pom:

  • the <parent> section will point to parent project.
  • the <dependency> sections will point to dependent artifacts.
  • others such as <plugin> sections that are not addressed by this toppic.

Now the problem is about those references that point to POMs of your own project. Those will typically have the same <groupId> and <version> as the one defined in the referenced pom. For <groupId> the solution is simply to use <groupId>${project.groupId}</groupId> but your groupId will normaly never change anyhow. But on the other hand the <version> will change often and this becomes a maintenance problem if you have to spread the versions of your artifacts all over the POMs. I know that this gap of maven is somehow covered by maven-release-plugin but discussions have shown that this is NOT always a suiteable workaround.

So following the maven concept "convention over configuration" maven should offer a way to express a project-internal reference that points to the current version of that module defined in pom.xml without explicitly knowing this version. The suggestion is to be able to omit the version in such case. This would allow to have the version as a single point of information in the according pom while references still have the chance to explicitly specify a (older) version.

Two views on a POM

At this point we have to distinguish that there are two different points of view when maven is looking at a POM:

  • For development of a project maven reads pom.xml files from the local disc.
  • For using artifacts that have already been deployed (or installed) maven retrieves *.pom files from a repository (in the end from local repository).

An important issue for a new maven feature is that it is compatible with other maven versions and therefore will NOT break existing builds in any way. Therefore the suggested feature is planned to be only visible for the development view. To archieve this goal, maven has to be changed in a way such that it automatically adds omitted <version> tags in POMs that are installed in or deployed to a repository. To avoid mistakes or missusage of such feature maven could also reject processing POMs with missing <version> tag, that are not read as pom.xml but retrieved from a repository (including local repo).

The solution in detail

When you call maven from your toplevel project (where the root pom.xml is), it will scan the entire project tree of your project adding all nodes to the reactor. Having this complete reactor, maven is able to determine the version of each module in the reactor from the according pom.xml that has been parsed. So in that case if an individual module is build (actual goal[s] are invoked) maven can logically complete all the omitted <version> tags for modules available in the reactor (This actually means that parsing, processing and validating pom.xml can no more be done in one single step). Now if maven has logically completed the POM, it can do its build as if the missing tags have been there from the start. The important thing is that ArtifactInstaller and ArtifactDeployer need to guarantee, that the pom.xml is no more copied as is (1:1) but rather a new file is written where the missing tags are added. So in the end some other maven user can NOT see if this feature was used or not and can still use a maven version that does NOT support this feature without problems.

But what if maven is invoked on a sub-tree of the project? Here we have to distinguish two things:

  • A <version> that was omitted in a <parent> section is easy to resolve. You follow the <relativePath> (../pom.xml by default) and look for the parent POM. If it is there, you can read it and have its version (like it already works but the version is then matched to the one specified in <parent>). If it is NOT there maven will simply fail with a message like "Parent POM not found at <relativePath>! You have to specify the version of the parent if it is not locally available".
  • A <version> that was omitted in a <dependency> section can only be resolved if the referenced module is included in the reactor. So if it is NOT part of the sub-tree where the build was invoked we have a problem to solve. However this can be solved with the reactor-mode (I think this is what MNG-2576 is about): You have to invoke maven in a way so that it not only walks the hierarchy up to the top-level POM but also down from top-level including all <modules> as if the reactor was build from top-level but the actual goals are only performed on the modules in the sub-tree from where maven was invoked. This should also work together with -N. Because this reactor-mode is NOT active by default for various reasons, maven should actively support the user with an according error message if an omitted <version> can NOT be resolved and maven was NOT started in the reactor mode: "Maven could NOT determine omitted version of <groupId:artifactId>! Please enable reactor-mode with the option -r."
  • No labels