Maven: POM files without a version in it?
In Maven 3.2.5 a feature has been introduced to be able to define a version
of a Maven project via properties ${revision}
, ${sha1}
and ${changelist}
which unfortuantely had some issues.
Those issues have been fixed with Maven 3.5.0-beta-1
and now you can define the version of a project by using the following properties:
${revision}
, ${sha1}
and ${changelist}
. The example below will show one
usage of this:
1 ..
2 <parent>
3 <groupId>com.soebes.smpp</groupId>
4 <artifactId>smpp</artifactId>
5 <version>2.2.1</version>
6 </parent>
7
8 <groupId>com.soebes.examples.j2ee</groupId>
9 <artifactId>parent</artifactId>
10 <version>${revision}</version>
11 <packaging>pom</packaging>
12 ..
For the simplicity of this example I use only ${revision}
but in practice you could
combine the different properties.
The above is a parent of a larger multi module build which contains serveral childs which look like this:
1
2 <modelVersion>4.0.0</modelVersion>
3
4 <parent>
5 <groupId>com.soebes.examples.j2ee</groupId>
6 <artifactId>parent</artifactId>
7 <version>${revision}</version>
8 </parent>
9
10 <artifactId>service</artifactId>
11 <dependencies>
12 <dependency>
13 <groupId>com.soebes.examples.j2ee</groupId>
14 <artifactId>service-client</artifactId>
15 <version>${project.version}</version>
16 </dependency>
17 ...
18
19 ..
Based on the above you can now build your project simply by using the following:
1mvn -Drevision=1.0.0-SNAPSHOT clean package
So there is no need to change the pom files and check them in. But there exists a
drawback. You need to define the -Drevision=...
for each call of Maven which
is not very convenient.
Starting with Maven 3.3.1 you can configure Maven
command line parameters in a .mvn/maven.config
file which could contain the
version definition like this:
1-Drevision=1.0.0-SNAPSHOT
So with Maven 3.3.1+ you can now simply call Maven via:
1mvn clean package
More convenient?
Hm... wait a second. What if i like to create a different version? Yes you need
to change the .mvn/maven.config
file and you should of course checkin the
change into your vcs.
No. This is not really needed, but recommended. You can overwrite the version
which is defined in the .mvn/maven.config
via command line like this:
1mvn clean package -Drevision=2.0.0-SNAPSHOT
What kind of alternatives exist? You can of course define your version of your project as a property within your pom file itself.
1 ..
2 <parent>
3 <groupId>com.soebes.smpp</groupId>
4 <artifactId>smpp</artifactId>
5 <version>2.2.1</version>
6 </parent>
7
8 <groupId>com.soebes.examples.j2ee</groupId>
9 <artifactId>parent</artifactId>
10 <version>${revision}</version>
11 <packaging>pom</packaging>
12 ..
13 <properties>
14 ...
15 <revision>2.5.0-SNAPSHOT</revision>
16 </properties>
So this means you do not need to have a supplemental file in your project
(like .mvn/maven.config
) if you not already have. Also for this property
means you can overwrite it via command like this:
1mvn clean package -Drevision=1.8.67-SNAPSHOT
Deployment
But now let us come to an important point of this whole story. What happens
if you do an deploy
of such things via:
1mvn clean deploy -Drevision=1.8.67-SNAPSHOT
The result in your repository will be having pom files which contain ${revision}
which is simply not correct and can cause other issues.
How to solve this problem? This can simply being achieved by using the flatten-maven-plugin and adding the following part to your pom file:
1<build>
2 <plugins>
3 <plugin>
4 <groupId>org.codehaus.mojo</groupId>
5 <artifactId>flatten-maven-plugin</artifactId>
6 <version>1.0.0</version>
7 <configuration>
8 <updatePomFile>true</updatePomFile>
9 </configuration>
10 <executions>
11 <execution>
12 <id>flatten</id>
13 <phase>process-resources</phase>
14 <goals>
15 <goal>flatten</goal>
16 </goals>
17 </execution>
18 <execution>
19 <id>flatten.clean</id>
20 <phase>clean</phase>
21 <goals>
22 <goal>clean</goal>
23 </goals>
24 </execution>
25 </executions>
26 </plugin>
27 </plugins>
28</build>
By using the above you can now simply do a deploy via:
1mvn clean deploy -Drevision=1.8.67-SNAPSHOT
and the resulting pom file within the repository will correctly
contain the resolved version 1.8.67-SNASPHOT
.
This makes it easy to change the version from within a CI/CD tool. For example in Jenkins you can add a parameter like this:
1mvn clean package -Drevision=1.0-${BUILD_NUMBER}-SNAPSHOT
Or make more sophisticated combinations of the properties
${revision}
, ${sha1}
and ${changelist}
.
Conclusion
In the end you are not able to completely ban the versions from your pom file but nearly 100% which means you do not need to repeat it in each of your parent entries in a multi module build.
Furthermore you have saved a lot of issues related to merge conflicts within branches in Maven builds caused by the different version number for the different branches, cause the version can simply being defined by the CI/CD solution or manually from command line.