In this blog post, I will describe a few scenarios where you want to update versions in a multi-module Maven project consistently. In these examples, you have both a parent POM, which is meant to contain common properties and configurations to be inherited throughout the other projects, and aggregator POMs, which are meant to be used only to build the multi-module project. Thus, the parent itself is NOT meant to be used to build the multi-module project.
The source code of the projects used in this post can be found here: https://github.com/LorenzoBettini/maven-versions-example.
I’m not saying that such a POM configuration and structure is ideal. I mean that it can be seen as a good practice to separate the concept of parent and aggregator POMs (though, typically, they are implemented in the same POM). However, in complex multi-module projects, you might want to separate them. In particular, as in this example, we can have different separate aggregator POMs because we want to be able to build different sets of children’s projects. The aggregators inherit from the parent to make things a bit more complex and interesting. Again, this is not strictly required, but it allows the aggregators to inherit the shared configurations and properties from the parent. However, this adds a few more (interesting?) problems, which we’ll examine in this article.
We’re going to use the standard Maven plugin’s goal: org.codehaus.mojo:versions-maven-plugin:set:
Description:
Sets the current project’s version and based on that change propagates that change onto any child modules as necessary.
This is the aggregator1 POM (note that it inherits from the parent and also mentions the parent as a child because we want to build the parent during the reactor, e.g., to deploy it):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.examples</groupId> <artifactId>example.parent1</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../example.parent1</relativePath> </parent> <artifactId>example.aggregator1</artifactId> <packaging>pom</packaging> <modules> <module>../example.parent1</module> <module>../example.child11</module> <module>../example.child12</module> </modules> </project> |
Let’s make sure we can build it:
1 2 3 4 5 6 |
[INFO] Reactor Summary for example.aggregator1 0.0.1-SNAPSHOT: [INFO] [INFO] example.parent1 .................................... SUCCESS [ 0.002 s] [INFO] example.child11 .................................... SUCCESS [ 1.932 s] [INFO] example.child12 .................................... SUCCESS [ 0.216 s] [INFO] example.aggregator1 ................................ SUCCESS [ 0.000 s] |
The aggregator2 is similar; here’s the build result:
1 2 3 4 5 6 |
[INFO] Reactor Summary for example.aggregator2 0.0.1-SNAPSHOT: [INFO] [INFO] example.parent2 .................................... SUCCESS [ 0.001 s] [INFO] example.child21 .................................... SUCCESS [ 0.757 s] [INFO] example.child22 .................................... SUCCESS [ 0.223 s] [INFO] example.aggregator2 ................................ SUCCESS [ 0.000 s] |
Note that parent2 has parent1 as a parent:
1 2 3 4 5 6 7 8 9 10 11 12 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.examples</groupId> <artifactId>example.parent1</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../example.parent1</relativePath> </parent> <artifactId>example.parent2</artifactId> <packaging>pom</packaging> </project> |
Let’s say we want to update the version of parent1 consistently. Where do we run the following Maven command?
1 2 3 |
mvn versions:set \ -DnewVersion=0.0.2-SNAPSHOT \ -DgenerateBackupPoms=false |
Let’s try to do that on the aggregator1:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[INFO] Reactor Summary for example.aggregator1 0.0.1-SNAPSHOT: [INFO] [INFO] example.parent1 .................................... SKIPPED [INFO] example.child11 .................................... SKIPPED [INFO] example.child12 .................................... SKIPPED [INFO] example.aggregator1 ................................ FAILURE [ 0.358 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.501 s [INFO] Finished at: 2023-02-04T18:47:14+01:00 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.codehaus.mojo:versions-maven-plugin:2.14.2:set (default-cli) on project example.aggregator1: Project version is inherited from parent. -> [Help 1] |
Maybe on the parent1?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[INFO] --------------------< com.examples:example.parent1 >-------------------- [INFO] Building example.parent1 0.0.1-SNAPSHOT [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.parent1 --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: /home/bettini/work/eclipse/maven/maven-versions-example/example.parent1 [INFO] Processing change of com.examples:example.parent1:0.0.1-SNAPSHOT -> 0.0.2-SNAPSHOT [INFO] Processing com.examples:example.parent1 [INFO] Updating project com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
It looks like it worked… or it didn’t?
As you can see, it updated only the version of parent1, and now all the other children will refer to an old version. It didn’t work!
In fact, if we try to build the whole project with the aggregator1, it fails:
1 2 3 4 5 6 7 8 9 |
[INFO] Scanning for projects... [ERROR] [ERROR] Some problems were encountered while processing the POMs: [FATAL] Non-resolvable parent POM for com.examples:example.aggregator1:0.0.1-SNAPSHOT: Could not find artifact com.examples:example.parent1:pom:0.0.1-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 4, column 10 @ [ERROR] The build could not read 1 project -> [Help 1] [ERROR] [ERROR] The project com.examples:example.aggregator1:0.0.1-SNAPSHOT (... example.aggregator1/pom.xml) has 1 error [ERROR] Non-resolvable parent POM for com.examples:example.aggregator1:0.0.1-SNAPSHOT: Could not find artifact com.examples:example.parent1:pom:0.0.1-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 4, column 10 -> [Help 2] [ERROR] |
Before going on, let’s revert the change of version in parent1.
Let’s add references to aggregators in parent1
1 2 3 4 |
<modules> <module>../example.aggregator1</module> <module>../example.aggregator2</module> </modules> |
Let’s run the Maven command on parent1:
1 |
[ERROR] Child module example.parent1/pom.xml of example.aggregator1/pom.xml forms aggregation cycle example.parent1/pom.xml -> example.aggregator1/pom.xml -> example.parent1/pom.xml @ |
That makes sense: the aggregator has the parent as a child, and the parent has the aggregator as a child.
But what if we help Maven a little to detect all the children without a cycle?
It looks like it is enough to “hide” the references to children inside a profile that is NOT activated:
1 2 3 4 5 6 7 8 9 10 11 |
<profiles> <profile> <!-- DON'T activate it, it's only to let Maven detect the the children --> <id>update-versions-only</id> <modules> <module>../example.aggregator1</module> <module>../example.aggregator2</module> </modules> </profile> </profiles> |
And the update works. All the versions are consistently updated in all the Maven modules:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.parent1 --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: example.parent1 [INFO] Processing change of com.examples:example.parent1:0.0.1-SNAPSHOT -> 0.0.2-SNAPSHOT [INFO] Processing com.examples:example.parent1 [INFO] Updating project com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator1 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child11 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child12 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.parent2 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator2 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child21 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child22 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
The important thing is that aggregator2 does not have parent1 as a module (just parent2), or the Maven command will not terminate.
We can also consistently update the version of a single artifact; if the artifact is a parent POM, the references to that parent will also be updated in children. For example, let’s update only the version of parent2 by running this command from the parent1 project and verify that the versions are updated consistently:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
mvn versions:set \ -DartifactId=example.parent2 \ -DnewVersion=0.0.3-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [INFO] [INFO] --------------------< com.examples:example.parent1 >-------------------- [INFO] Building example.parent1 0.0.2-SNAPSHOT [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.parent1 --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: example.parent1 [INFO] Processing change of com.examples:example.parent2:0.0.2-SNAPSHOT -> 0.0.3-SNAPSHOT [INFO] Processing com.examples:example.aggregator2 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.2-SNAPSHOT to 0.0.3-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child21 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.2-SNAPSHOT to 0.0.3-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child22 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.2-SNAPSHOT to 0.0.3-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
Unfortunately, this is not the correct result: the version of parent2 has not been updated. Only the references to parent2 in the children have been updated to a new version that will not be found.
For this strategy to work, parent2 must have its version, not the one inherited from parent1.
Let’s verify that: let’s manually change the version of parent2 to the one we have just set in its children:
1 2 3 4 5 6 7 8 9 10 |
<parent> <groupId>com.examples</groupId> <artifactId>example.parent1</artifactId> <version>0.0.2-SNAPSHOT</version> <relativePath>../example.parent1</relativePath> </parent> <artifactId>example.parent2</artifactId> <packaging>pom</packaging> <version>0.0.3-SNAPSHOT</version> |
And let’s try to update to a new version the parent2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
mvn versions:set \ -DartifactId=example.parent2 \ -DnewVersion=0.0.4-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [INFO] [INFO] --------------------< com.examples:example.parent1 >-------------------- [INFO] Building example.parent1 0.0.2-SNAPSHOT [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.parent1 --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: /home/bettini/work/eclipse/maven/maven-versions-example/example.parent1 [INFO] Processing change of com.examples:example.parent2:0.0.2-SNAPSHOT -> 0.0.4-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
Nothing has changed… it did not work.
Let’s try and be more specific by specifying the old version (after all, we’re running this command from parent1 asking to change the version of a specific child):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
mvn versions:set \ -DartifactId=example.parent2 \ -DoldVersion=0.0.3-SNAPSHOT \ -DnewVersion=0.0.4-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [INFO] [INFO] --------------------< com.examples:example.parent1 >-------------------- [INFO] Building example.parent1 0.0.2-SNAPSHOT [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.parent1 --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: example.parent1 [INFO] Processing change of com.examples:example.parent2:0.0.3-SNAPSHOT -> 0.0.4-SNAPSHOT [INFO] Processing com.examples:example.parent2 [INFO] Updating project com.examples:example.parent2 [INFO] from version 0.0.3-SNAPSHOT to 0.0.4-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator2 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.3-SNAPSHOT to 0.0.4-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child21 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.3-SNAPSHOT to 0.0.4-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child22 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.3-SNAPSHOT to 0.0.4-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
This time it worked! It updated the version in parent2 and all the children of parent2.
Let’s reset all the versions to the initial state.
Let’s remove the “hack” of child modules from parent1 and create a brand new aggregator that does not inherit from any parent (in fact, it configures the versions plugin itself) but serves purely as an aggregator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.examples</groupId> <artifactId>example.update.aggregator</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>../example.aggregator1</module> <module>../example.aggregator2</module> </modules> <build> <pluginManagement> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>versions-maven-plugin</artifactId> <version>2.14.2</version> </plugin> </plugins> </pluginManagement> </build> </project> |
Let’s try to run the version update from this aggregator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
mvn versions:set \ -DnewVersion=0.0.2-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] example.parent1 [pom] [INFO] example.child11 [jar] [INFO] example.child12 [jar] [INFO] example.aggregator1 [pom] [INFO] example.parent2 [pom] [INFO] example.child21 [jar] [INFO] example.child22 [jar] [INFO] example.aggregator2 [pom] [INFO] example.update.aggregator [pom] [INFO] [INFO] ---------------< com.examples:example.update.aggregator >--------------- [INFO] Building example.update.aggregator 0.0.1-SNAPSHOT [1/9] [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.update.aggregator --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: /home/bettini/work/eclipse/maven/maven-versions-example/example.update.aggregator [INFO] Processing change of com.examples:example.update.aggregator:0.0.1-SNAPSHOT -> 0.0.2-SNAPSHOT [INFO] Processing com.examples:example.update.aggregator [INFO] Updating project com.examples:example.update.aggregator [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary for example.update.aggregator 0.0.1-SNAPSHOT: [INFO] [INFO] example.parent1 .................................... SKIPPED [INFO] example.child11 .................................... SKIPPED [INFO] example.child12 .................................... SKIPPED [INFO] example.aggregator1 ................................ SKIPPED [INFO] example.parent2 .................................... SKIPPED [INFO] example.child21 .................................... SKIPPED [INFO] example.child22 .................................... SKIPPED [INFO] example.aggregator2 ................................ SKIPPED [INFO] example.update.aggregator .......................... SUCCESS [ 0.407 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
It updated the version of the aggregator only! That’s not what we want.
Let’s revert the change.
We know that we can use the artifactId
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
mvn -f example.update.aggregator \ versions:set \ -DartifactId=example.parent1 \ -DnewVersion=0.0.2-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Reactor Build Order: [INFO] [INFO] example.parent1 [pom] [INFO] example.child11 [jar] [INFO] example.child12 [jar] [INFO] example.aggregator1 [pom] [INFO] example.parent2 [pom] [INFO] example.child21 [jar] [INFO] example.child22 [jar] [INFO] example.aggregator2 [pom] [INFO] example.update.aggregator [pom] [INFO] [INFO] ---------------< com.examples:example.update.aggregator >--------------- [INFO] Building example.update.aggregator 0.0.1-SNAPSHOT [1/9] [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.update.aggregator --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: example.update.aggregator [INFO] Processing change of com.examples:example.parent1:0.0.1-SNAPSHOT -> 0.0.2-SNAPSHOT [INFO] Processing com.examples:example.parent1 [INFO] Updating project com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator1 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child11 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child12 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.parent2 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator2 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child21 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child22 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary for example.update.aggregator 0.0.1-SNAPSHOT: [INFO] [INFO] example.parent1 .................................... SKIPPED [INFO] example.child11 .................................... SKIPPED [INFO] example.child12 .................................... SKIPPED [INFO] example.aggregator1 ................................ SKIPPED [INFO] example.parent2 .................................... SKIPPED [INFO] example.child21 .................................... SKIPPED [INFO] example.child22 .................................... SKIPPED [INFO] example.aggregator2 ................................ SKIPPED [INFO] example.update.aggregator .......................... SUCCESS [ 0.422 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
What if the same child is included in our aggregators aggregator1 and aggregator2? For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.examples</groupId> <artifactId>example.parent1</artifactId> <version>0.0.1-SNAPSHOT</version> <relativePath>../example.parent1</relativePath> </parent> <artifactId>example.aggregator1</artifactId> <packaging>pom</packaging> <modules> <module>../example.parent1</module> <module>../example.child11</module> <module>../example.child12</module> <module>../example.child22</module> </modules> </project> |
We get an error if we try to update the version as above because the same module is present twice in the same reactor:
1 2 3 4 5 6 7 8 |
mvn -f example.update.aggregator \ versions:set \ -DartifactId=example.parent1 \ -DnewVersion=0.0.2-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [ERROR] [ERROR] Project 'com.examples:example.child22:0.0.1-SNAPSHOT' is duplicated in the reactor @ |
But what if we apply the same trick of the modules inside a profile in this new aggregator project, which is meant to be used only to update versions consistently?
For example,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.examples</groupId> <artifactId>example.update.aggregator</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <profiles> <profile> <!-- DON'T activate it, it's only to let Maven detect the the children --> <id>update-versions-only</id> <modules> <module>../example.aggregator1</module> <module>../example.aggregator2</module> </modules> </profile> </profiles> <build> <pluginManagement> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>versions-maven-plugin</artifactId> <version>2.14.2</version> </plugin> </plugins> </pluginManagement> </build> </project> |
This time, the version update works even when the same module is present in both our aggregator1 and aggregator2! Moreover, versions are updated only once in the module mentioned in both our aggregators:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
mvn -f example.update.aggregator \ versions:set \ -DartifactId=example.parent1 \ -DnewVersion=0.0.2-SNAPSHOT \ -DgenerateBackupPoms=false [INFO] Scanning for projects... [INFO] [INFO] ---------------< com.examples:example.update.aggregator >--------------- [INFO] Building example.update.aggregator 0.0.1-SNAPSHOT [INFO] --------------------------------[ pom ]--------------------------------- [INFO] [INFO] --- versions-maven-plugin:2.14.2:set (default-cli) @ example.update.aggregator --- [INFO] Searching for local aggregator root... [INFO] Local aggregation root: example.update.aggregator [INFO] Processing change of com.examples:example.parent1:0.0.1-SNAPSHOT -> 0.0.2-SNAPSHOT [INFO] Processing com.examples:example.parent1 [INFO] Updating project com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator1 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child11 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child12 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.parent2 [INFO] Updating parent com.examples:example.parent1 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.aggregator2 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child21 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] Processing com.examples:example.child22 [INFO] Updating parent com.examples:example.parent2 [INFO] from version 0.0.1-SNAPSHOT to 0.0.2-SNAPSHOT [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ |
Maybe, this time, this is not to be considered a hack because we use this aggregator only as a means to keep track of version updates consistently in all the children of our parent POMs.
As I said, these might be seen as complex configurations; however, I think it’s good to experiment with “toy” examples before applying version changes to real-life Maven projects, which might share such complexity.
One of the best articles to help me grasp Maven’s general logic about parents/modules/dependencies, thank you!
However, reading about things I CAN do with POMs, I still struggle to understand how I’m SUPPOSED to configure a big multi-module project. I just want it to be simple and use as few features as I have to, and not to juggle 20+ confusing profiles that interact with each other in confusing ways. Maven’s own documentation is quick to talk about all the features they have, but no guidance on how to cleanly reorganize a multi-module project.
Can you recommend a reference on how structure a maven project?
Thank you Daniel for the kind words! 🙂
Unless strictly required, I’d suggest you to keep the structure of your Maven projects simple, following conventions if you can (e.g., nested directories).
Of course, if needed, you can re-structure it and in that case, my blog post is meant to shed some light on how to handle for example version upgrades correctly.
Small ad: in my TDD book https://leanpub.com/tdd-buildautomation-ci there’s a huge chapter on Maven 😉