Maven Multi-Module Dependency Conflicts

Deniz G
3 min readFeb 4, 2021

--

If you have tried to centralize dependency versions, you must have encountered the following warning message.

[WARNING] Some problems were encountered while building the effective model for group-id:artifact-id:jar:0.1.4-RELEASE
[WARNING] ‘version’ contains an expression but should be a constant. @ group-id:artifact-id:${module1.version}
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.

This will likely cause an error if non-constant versions are not used correctly.

We have around 20 infrastructure libraries to help software development in microservice architecture and we use multi-module structure to manage them easily. These modules can also be interdependent. For example, the validation module is used by 3 different modules (rest, module1, module2).

If validation is upgraded, it is necessary to get upgrade to other modules that use it. If these version numbers were constant, upgrading would be troublesome.

The version numbers are centralized at parent pom, and the modules refers these versions.

<groupId>company-name</groupId>
<artifactId>infra</artifactId>
<properties>
<java.version>15</java.version>

...
<validation.version>0.1.12-RELEASE</validation.version>
<rest.version>0.1.19-RELEASE</rest.version>

<other1.version>0.1.10-RELEASE</other1.version>
<other2.version>0.1.10-RELEASE</other2.version>
...
</properties>

In validation module pom

<parent>
<groupId>company-name</groupId>
<artifactId>infra</artifactId>
</parent>
<artifactId>validation</artifactId>
<version>${validation.version}</version>

In rest module pom

<parent>
<groupId>company-name</groupId>
<artifactId>infra</artifactId>
</parent>
<artifactId>rest</artifactId>
<version>${rest.version}</version>
<dependencies>
<dependency>
<groupId>company-name</groupId>
<artifactId>validation</artifactId>
<version>${validation.version}</version>

</dependency>
...
</dependencies>

If we want to version from validation, we’ll simply increment version numbers from validation, rest, module1 and module2. That’s all.

Problem

Let’s say that we have prototype microservice which has rest dependency.

<dependency>
<groupId>company-name</groupId>
<artifactId>rest</artifactId>
<version>0.1.19-RELEASE</version>

</dependency>

I want to take build from validation (0.1.12-RELEASE to 0.1.13-RELEASE). So I need to also take build from rest (0.1.19-RELEASE to 0.1.20-RELEASE)

mvn clean install -pl validation,rest[INFO] -------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] validation [jar]
[INFO] rest [jar]
...
[INFO] -------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] validation 0.1.13-RELEASE .......... SUCCESS [ 8.393 s]
[INFO] rest 0.1.20-RELEASE ................ SUCCESS [ 9.788 s]
[INFO] -------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------

The build is successful.

Let’s upgrade rest dependency in prototype project.

<dependency>
<groupId>company-name</groupId>
<artifactId>rest</artifactId>
<version>0.1.20-RELEASE</version>

</dependency>

Although the rest version is new, the validation still remained in the old version.

This only happens when you want to compile the specific modules using the -pl parameter. If all modules were compiled without the -pl parameter, this would not be a problem.

Why?

Because, all modules in the project are using the parent pom but the parent pom is not built by -pl parameter. So, the module versions are defined still shows the last acquired build and the modules use last acquired build’s versions. You can check the contents of the parent pom from the local maven repository (.m2).

Why not problem without -pl?

If you don’t use -pl parameter, the build starts from parent pom, you can see easily this from build logs.

mvn clean install [INFO] -------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] infra [pom]
[INFO] validation [jar]
[INFO] rest [jar]
...

Solution

First, take build from parent pom

mvn -N clean install (or mvn --non-recursive clean install)

Then, take build the modules you need.

mvn clean install -pl validation,rest

--

--

Recommended from Medium

Lists

See more recommendations