# Nonsensical Maven is still a Gradle problem

DevFeed: [Nonsensical Maven is still a Gradle problem](<https://devfeed.tech/articles/nonsensical-maven-is-still-a-gradle-problem-20949.md>)

Original publisher: [Read original article](<https://jakewharton.com/nonsensical-maven-is-still-a-gradle-problem/>)

Published: 2024-03-28T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [Maven](<https://devfeed.tech/topics/maven.md>), [Gradle](<https://devfeed.tech/topics/gradle.md>)

Tags: [build-system](<https://devfeed.tech/tags/build-system.md>), [dependencies](<https://devfeed.tech/tags/dependencies.md>), [dependency](<https://devfeed.tech/tags/dependency.md>), [jvm](<https://devfeed.tech/tags/jvm.md>)

## AI overview

The article argues that Maven's default dependency resolution strategy is problematic for libraries built with Gradle. It explains dependency graphs and contrasts Gradle's default preference for newer versions with Maven's "nearest definition" rule, where declaration order can cause an older transitive dependency to win.

## Source excerpt

There was a time when I used Maven heavily, but today all the libraries I work on build with Gradle. Even though I'm publishing with Gradle, consumers can use Gradle, Maven, Bazel, jars in libs/ (but please don't), or anything else. That's a huge JVM ecosystem win! In general, I don't have to think about what build system someone is using. I'm not here to debate subjective pros and cons of one versus any other. There is one notable exception, however. Maven's dependency resolution strategy is objectively bonkers. And if we want to support Maven consumers, we need to think about it. If you already are familiar with the concept of dependency resolution, you can skip to the nonsense. Dependency resolution primer Chances are your build system of choice (or a separate dependency resolver tool) gives you a declarative way to describe your dependencies. At build time, those declarations are resolved to .jars which can be put on the compiler classpath. Sometimes we call this a dependency tree, but it's actually a dependency graph, as separate nodes can converge back to something common to both. Project (build.gradle) ├── A │ └── B │ └── C v1.0 └── D └── C v1.0 If library B and library D agree on the version of library C, then that is the .jar version which is used. If they disagree on versions, some policy needs to decide the appropriate single version to use. Pop quiz: If library B wants version 1.1 of library C, and library D wants version 1.0 of library C, which single version of C should we use? Project (build.gradle) ├── A │ └── B │ └── C v1.1 └── D └── C v1.0 This is not a trick question. Hopefully the answer feels obvious: you use the newer version, 1.1. That version is probably compatible with 1.0, so it's safe for both library B and library D to use. We can't know for sure, to be clear, but it's a safe choice. This behavior is the default in many dependency resolvers, including the one inside Gradle. The nonsense When building with Maven, given two dependencies who