Technical blog

When to (not) use mavenLocal() in your Gradle build script

When to (not) use mavenLocal() in your Gradle build script

Technical Blog
Image
Author
Bruno Berstel
Reading Time
5 minutes

Gradle as build tool

If you’re like me and you work in a company that uses Gradle as its build tool, you may have wondered, while writing the build scripts for your project, what exactly should go into that repositories block. And in particular whether or not to include mavenLocal(), and if so where: as the first element? the last one? The short answer is that you don’t want to include it.

Repositories

As you most probably know if you’re reading this, Gradle can leverage the Maven system of components (such as Java libraries) and repositories (such as Sonatype's Nexus). Using those, you just need to declare a dependency like the following in the build script of your Java application:
dependencies {
  implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
  // ...
}
and Gradle will take care of retrieving version 2.9.9 of the core library of Jackson provided by FasterXML, and include it in the appropriate class paths when compiling or running your application.

This, provided Gradle knows where to look for this library. And that is precisely the point of the repositories block, that could typically read as follows:
repositories {
  maven {
    url "http://nexus.mycompany.loc/repository/internal"
    mavenCentral()
  }
}
In the repositories block above, you state that when looking for a dependency, Gradle should first query the internal Nexus repository of your company, then the central Maven repository at https://repo1.maven.org/maven2/ .
The central repository is where Gradle will find all publicly available libraries, such as Jackson. Your company may also use an internal repository to store the software components shared between projects, or between modules of a project.

Imagine that your application, in addition to Jackson, uses code from a shared library of DTOs for your project. Its dependencies could then read:
dependencies {
  implementation "com.mycompany.myproject:common-dtos:1.0.0-SNAPSHOT"
  implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
  // ...
}
When compiling your application code, Gradle will look for the common-dtos and jackson-core libraries, first in its dependency cache in your home directory, then in your company’s internal repository, then in the central Maven repository.

Now, what about mavenLocal?

Up to here, everything works as expected. Yet, you may come across some Gradle build scripts with a repositories block that would read as follows:
repositories {
  maven {
    mavenLocal()
    url "http://nexus.mycompany.loc/repository/internal"
    mavenCentral()
  }
}
At first, this looks sensible: don’t query the internal or central repository if the dependency is already present in the local repository. Whatever “the local repository” may actually mean…

It turns out that the mavenLocal() repository is not the Gradle dependency cache. It is a repository where you can deploy components with ./gradlew publishToMavenLocal (assuming you use the maven-publish Gradle plugin ). Now, why would you like to deploy to a local repository? My take is, you don’t.

The typical case where I would consider using a local repository is to test a change in a shared library without publishing it to a repository visible to other people than me, so that I’m sure of what I publish, when I publish it. However, there are better ways to achieve that.

First case: the shared library that I want to test is in the same Gradle build as the code that uses it. (Let me remind that in Gradle parlance, a 'build' is the code base that is considered when running a command such as ./gradlew build. This is what Eclipse refers to as a workspace, or IntelliJ IDEA as a project.) In that case, where the common DTOs library is built from, say, a common-dtos subfolder of the project root, specifying the dependencies of the application as a project dependency ) is enough:
dependencies {
  implementation project(":common-dtos")
  implementation "com.fasterxml.jackson.core:jackson-core:2.9.9"
  // ...
}
Second case: the shared library is in a different Gradle build, typically its source code is in a different Git repository (let us name it common-components). Then I will use the composite build feature to instruct Gradle to use the version of the common components that I cloned, rather than the one from the repository, when building my application. To this end, assuming that I have cloned the two Git repositories next to each other on my disk (if not, it’s just a matter of setting up the right relative path), I simply have to add the following line in the settings.gradle file at the root of of my application:
includeBuild "../common-components"


Conclusion

Although you may come across some Gradle build scripts that include mavenLocal() in the list of repositories where to look dependencies from, I cannot think of a good reason to do so. There are use cases where mavenLocal() could look like a solution, and maybe it was at a time when project dependencies and composite builds were not available in Gradle. But now they are. Even worse: the official Gradle documentation warns about different issues that could arise when using mavenLocal().

Originally published March 27, 2020, modified September 16, 2021

Keep up to date with our Medium blog .


Related Resources

DecisionBrain is proud to announce that it has a technology licensing and distribution agreement with IBM to be a partner reseller of IBM Cplex Optimization Studio....

Artificial Intelligence
06/05/2021

DecisionBrain is now a member of AfIA (Association française pour l'Intelligence Artificielle), the French Association for Artificial Intelligence....

world image
06/05/2021

DecisionBrain is proud to announce that it has signed a business partner agreement with the Japanese company Advances Technology Institute, Inc (ATI)....

ROADEF event
22/04/2021

DecisionBrain is proud to announce that this year as well, for the 5th year in a row, we will be one of the sponsors of the 22nd ROADEF Mulhouse 2021....

One year has passed, after a lot of effort and working hours, today DecisionBrain is glad to inform you that Decision Optimization Center 4.0.1 is now available!...

Download the DecisionBrain Company Brochure PDF, We Combine Optimization and Artificial Intelligence to Create Innovative Solutions that Drive Operational Efficiency...

Download our Professional Services Methodology PDF, DecisionBrain has developed Services best practices, trainings and tools tosupport our customers in the journey to reach...

DOC Optimization server
01/04/2020

Download the Field Service Management Whitepaper by DecisionBrain. Increase your knowledge of the industry with key tactics for choosing your software solution. Includes a...

DOC Optimization server
01/04/2020

Download the DOC Datasheet from DecisionBrain. Learn more about the important features included in DOC 4.0. this included components, customers and use cases....

Operations Research (OR) is a science with solid grounds coming from mathematics (graph theory, combinatorial optimization, convex and non convex geometry …), artificial...

In 2018 DecisionBrain’s Bike Sharing Solution was a finalist at the IBM Beacon Award for Outstanding Analytics Solution. The IBM Beacon awards are given to IBM’s Business...

ROADEF event
24/03/2020

ROADEF rewarded DecisionBrain twice with ‘Les pros de la RO’ for the best OR project of the year: In 2018 for our Bike Sharing Solution In 2015 for Multi-Vessel Optimization...

Download the Datasheet for DOC OS . Decision Optimization Center Optimization Server is powered by DecisionBrain and utilized by IBM as a crucial part of the overall DOC 4.0...