Reputation: 8206
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
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
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.
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