Skip to content

Why doesn’t Gradle or Maven have a dependency version lock file?

I’ve recently been introduced to the concept of a dependency version lock file when reading about package managers like NPM, Yarn, Paket, Cargo, etc. My understanding is that it is a file that lists all direct and transitive dependencies along with their exact version number so subsequent builds are guaranteed to use an equivalent set of dependencies. This seems to be a desirable feature since many package managers have or are adopting the concept.

My questions are then:

  1. Why doesn’t Maven or Gradle use a lock file? Or if they do, why haven’t I seen it?

  2. What are the pros and cons of allowing version ranges in a package manager’s dependency resolution strategy vs only allowing exact versions?

Answer

  1. Maven does not have a way of to achieve what you are asking for. Even if you set specific versions for your direct dependencies, which you should, your transitive dependencies can easily be unintentionally changed due to a seemingly unrelated change. For example, adding a dependency on a new library can give you an older version of an existing transitive dependency.

    What you need is to have a dependencyManagement section that lists all your direct and transitive dependencies. You will still not be able to detect if a transitive dependency is removed or added which is a feature that, for example, NPM provides. The problem with missing that is that all your dependencies are no longer in the dependencyManagement section. To detect those changes you could use something like dependency-lock-maven-plugin which I have written. Using it will also make it less important to have everything in a dependencyManagement section since changes in transitive dependencies will be detected.

    I would also recommend having https://maven.apache.org/enforcer/enforcer-rules/requireUpperBoundDeps.html in your build since Maven chooses the versions of the transitive dependencies that are closes in the tree and not, as you would expect, the highest version.

    I have seen many runtime problems caused by developers accidentally changing transitive dependencies.

    TL;DR: You do need something like a lock file in Maven, but it is not there due to historical ideological reasons.

  2. I would not recommend using version ranges since they make your build not reproducible. Neither does it behave as you would believe when it comes to transitive dependencies.