Maven user's quickly realize that it is a good idea to force a fixed (or at least minimum) version of Maven to be used to build their Maven project. Initially one may gravitate towards using the following pom snippet:
<prerequisites>
<maven>2.0.10</maven>
</prerequisites>
Looks good, except there are a couple gotchas
1. Typos. If you make one then you will get no warning or complaints from maven. You might as well have this.
<prerequisites>
<maven>Maven treats this string as older than any Maven version you might use</maven>
</prerequisites>
A bug is even more likely if you do this:
<prerequisites>
<maven>${maven.min-version}</maven>
</prerequisites>
Let's say that property can't be resolved for whatever reason - typos? - again Maven will treat that 'version' as older than any valid Maven version you could be executing the POM with. This is actually not a bug but by design since Maven does not force project's ( in this case Maven itself) to a strict version number specification.
2. Another problem is that
section is not even used at all by the next major version of Maven 3.x as of today. So even if you did have it right, it is not future proof.
3. Finally maven considers versions like "1.0-alpha-2" to be newer than "1.0-alpha-15" as of Maven 2.x series at least. A bug indeed in the version compare logic - the failing test cases being commented out in the source code. Although Maven 3.x ignores prerequisites in pom, at least the version comparison noted here is fixed.
4. Lastly the <maven> element does not handle version ranges. So when it sees [2.0.6,2.0.8], we are just back to problem 1.
So what to do?
Use the maven-enforcer-plugin instead. The benefits are:
1. Many different rules supported, not just Maven version.
2. Write your own rules.
3. Version ranges are supported.
4. Version comparisons are more robust.
5. Bind the version check to Maven lifecycle phases or profiles.
Below is an example configuration for the plugin to require a minimum Maven version 2.0.9 and above. The unique thing about this example is that there are three executions, one for each pre-defined Maven build lifecycle. Usually you just see the first execution only, which is bound to the validate phase of the default lifecycle. However if one were to do mvn clean
or mvn site
then the version validation would not be enforced since those goals do not have a validate phase. Having all three executions covers all the bases.
The other best practice is define a property to hold the Maven versions so that it can be changed in one place only or manipulated on the cmd line.
<properties>
<maven.min-version>2.0.9</maven.min-version>
</properties>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-default</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>[${maven.min-version},)</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
<execution>
<id>enforce-clean</id>
<phase>pre-clean</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>[${maven.min-version},)</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
<execution>
<id>enforce-site</id>
<phase>pre-site</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>[${maven.min-version},)</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>