2

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.

David
  • 7,652
  • 21
  • 60
  • 98

2 Answers2

2

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.

norbjd
  • 10,166
  • 4
  • 45
  • 80
  • 1
    Up voting for comprehensive information, however if i run this command: `mvn dependency:tree | grep -i dynamo | wc -l` the result is `1`. Unless I've misunderstood what this tree is showing me - if there were some type of conflicting transitive dependency wouldn't dynamo show up twice in the tree, rather than once? – David Aug 12 '18 at 10:26
  • @DavidGoate If you run `mvn dependency:tree -Dverbose`, Maven will show you **all dependencies**, with messages like `omitted for conflict with x.x.x` for dependencies evicted because of versions conflicts. Thus, you should see what artifacts depends on `aws-java-sdk-dynamodb`, and the different versions. – norbjd Aug 12 '18 at 12:58
  • thanks for the recommendation, this is indeed interesting and showed me information that was new to me. The command `mvn dependency:tree -Dverbose | grep -i dynamo` shows me just `[INFO] +- com.amazonaws:aws-java-sdk-dynamodb:jar:1.11.125:compile`, so no message about duplicates/conflicts (others in the list do but not dynamo) Thanks again for trying, but this still seems slightly unsolved to me as to how this specific dependency is being resolved to that version. – David Aug 13 '18 at 08:40
  • Hmm that's weird... Could you post your POM in your question, or at least reproduce a minimal POM leading to the same situation? – norbjd Aug 13 '18 at 08:43
  • Thanks for your help, very valuable and led me to discover the underlying issue. – David Aug 13 '18 at 15:13
  • @David were you able to figure out why duplicates/conflicts information was not show by mvn dependency:tree -Dverbose | grep -i dynamo? – Prashanth Debbadwar Apr 06 '22 at 12:36
1

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.

David
  • 7,652
  • 21
  • 60
  • 98