David
David

Reputation: 8206

Is there a way to tell why a maven dependency is at a certain version

I have a spring boot app (which has a parent pom) and generally manages plenty of dependencies in terms of their version.

If I add this to my pom.xml

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-dynamodb</artifactId>
</dependency>

And list the dependencies it indicates that version is not the latest:

./mvnw dependency:list | grep dynamo
[INFO]    com.amazonaws:aws-java-sdk-dynamodb:jar:1.11.125:compile 

At time of writing the latest version is 1.11.838, my current version is many months "out of date".

My IDE usually does a good job of showing me when a dependency is being "managed" e.g. by a parent pom. But in this case it doesn't indicate that this is the case.

My thinking is perhaps a transitive dependency is influencing this, but I'd like a more empirical way to find out.

Of course I could just add an explicit version element to the dependency or add an explicit dependency management element for this dependency. But my question is more academic in nature, I want to understand why maven determines that this is the right version to resolve.

Ideally what I'm trying to learn is what tooling or processes exist to "debug" this, e.g. a particular maven plugin which might help show how a version was resolved.

The result of: mvn dependency:tree | grep -i dynamo | wc -l is 1. Which (I think) indicates that it's not appearing multiple times in transitive dependencies.

Upvotes: 3

Views: 1357

Answers (2)

David
David

Reputation: 8206

Riddle solved, I was using a BOM spring-cloud-dependencies:Edgware.SR4 which internally uses spring-cloud-dependencies-parent:Edgware.SR4 which then uses spring-cloud-aws-dependencies:1.2.3.RELEASE which finally references aws-java-sdk-bom:1.11.125 as shown here.

Upvotes: 1

norbjd
norbjd

Reputation: 11287

Maven uses a "nearest wins" heuristic to resolve dependencies (read more about Dependency Mechanism).

Here, you probably have two dependencies depending on the same artifact com.amazonaws:aws-java-sdk-dynamodb, but with different versions (1.11.125 and another version).

When there is a conflict (see "Dependency mediation" in the guide I provided above), Maven resolves it by picking the "nearest" version from the root of your project. Below is an example :

             +----------------+
             |                |
             |  your project  |
             |                |
             +----+------+----+
                  |      |
            +-----+      +-----+
            |                  |
    +-------v------+    +------v-------+
    | dependency A |    | dependency B |
    +-------+------+    +------+-------+
            |                  |
            |                  |
+-----------v---------+        |
|    com.amazonaws    | +------v-------+
|aws-java-sdk-dynamodb| | dependency C |
|      1.11.125       | +------+-------+
+---------------------+        |
                               |
                     +---------v-----------+
                     |    com.amazonaws    |
                     |aws-java-sdk-dynamodb|
                     |       1.11.838      |
                     +---------------------+

Let's say your project depends on dependencies A and B, and those dependencies transitively depends on two different versions of aws-java-sdk-dynamodb (1.11.125 and 1.11.838). Since version 1.11.125 is "nearer" from the root, then this version is picked. That's probably what happens in your case.

If you need to use this dependency in your own code, I recommend you to set explicitly the version of the artifact, and not relying on Maven choice.

Additional info

Since Maven 2.0.9, if there is a conflict and no "nearest" artifact (in the previous example, if B have depended directly on 1.11.838 version), then the version picked depends if A is declared before or after B in your pom.xml. If A was declared first, then the version 1.11.125 would have been chosen.

Upvotes: 3

Related Questions