Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven and Ivy dependency resolution fails with Gradle 6.0

I have a working project that has a dependency on a maven artifact produced by a peer component like this:

repositories {
   ivy {
       url "../cnf/local"
   }
}

configurations {
  ejbTools
}

dependencies {
  ejbTools 'test:com.ibm.ws.ejbcontainer.fat_tools:1.+'
}

The dependency test:com.ibm.ws.ejbcontainer.fat_tools:1.+ fails to resolve with Gradle 6.0 with the following error:

> Task :com.ibm.ws.ejbcontainer.async_fat:addEJBTools FAILED

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/aguibert/dev/git/open-liberty/dev/com.ibm.ws.ejbcontainer.async_fat/build.gradle' line: 32

* What went wrong:
Execution failed for task ':com.ibm.ws.ejbcontainer.async_fat:addEJBTools'.
> Could not resolve all files for configuration ':com.ibm.ws.ejbcontainer.async_fat:ejbTools'.
   > Could not find any matches for test:com.ibm.ws.ejbcontainer.fat_tools:1.+ as no versions of test:com.ibm.ws.ejbcontainer.fat_tools are available.
     Searched in the following locations:
       - https://repo.maven.apache.org/maven2/test/com.ibm.ws.ejbcontainer.fat_tools/maven-metadata.xml
       - http://public.dhe.ibm.com/ibmdl/export/pub/software/olrepo/test/com.ibm.ws.ejbcontainer.fat_tools/maven-metadata.xml
       - file:/Users/aguibert/dev/git/open-liberty/dev/cnf/local/test/com.ibm.ws.ejbcontainer.fat_tools/
       - file:/Users/aguibert/dev/git/open-liberty/dev/cnf/local/test/com.ibm.ws.ejbcontainer.fat_tools/1.0.33.201909241016/ivy-1.0.33.201909241016.xml
     Required by:
         project :com.ibm.ws.ejbcontainer.async_fat

Context

Currently my project is using Gradle 5.5 and can be built with Java 8, 11, or 12. I am trying to get it working with Java 13 too so I am trying to upgrade to Gradle 6.0.

It seems that there is a general behavior change with the way wildcarded dependencies work in Gradle now (for example com.foo:bar:1.+).

like image 487
Andy Guibert Avatar asked Sep 25 '19 15:09

Andy Guibert


People also ask

Does Gradle use Ivy?

A published Ivy module can be consumed by Gradle (see Declaring Dependencies) and other tools that understand the Ivy format. You can learn about the fundamentals of publishing in Publishing Overview.

What is Dependencymanagement in Gradle?

In most cases, a project relies on reusable functionality in the form of libraries or is broken up into individual components to compose a modularized system. Dependency management is a technique for declaring, resolving and using dependencies required by the project in an automated fashion.

Why Gradle 6 0 fails to resolve artifacts from mavenlocal?

Gradle 6.0 fails to resolve artifacts from the mavenLocal () repository. The artifact was published using the maven-publish plugin. In the local maven repository metadata was published as maven-metadata-local.xml (as before). However Gradle 6.0 seems to be exclusively looking for a file named maven-metadata.xml - which isn't there.

How does Gradle know what version of Maven a repository is?

For Maven repositories, Gradle will use the maven-metadata.xml which provides information about the available versions. For Ivy repositories, Gradle will resort to directory listing. This process results in a list of candidate versions that are then matched to the dynamic version expressed.

How does Gradle resolve dependencies?

Given a required dependency, with a version, Gradle attempts to resolve the dependency by searching for the module the dependency points at. Each repository is inspected in order. Depending on the type of repository, Gradle looks for metadata files describing the module (.module,.pom or ivy.xml file) or directly for artifact files.

What is Apache Ivy Gradle?

Apache Ivy is a very flexible dependency management tooling. It offers the possibility to customize dependency resolution, including conflict resolution. This flexibility comes with the price of making it hard to reason about. Gradle will consider all requested versions, wherever they appear in the dependency graph.


1 Answers

According to this Gradle issue, there is a breaking change in behavior in Gradle 6.0. Before, Gradle would automatically check for artifact metadata (e.g. maven-metadata.xml), but in order to improve performance it seems that Gradle 6.0 no longer does this by default.

There are 2 possible solutions to this problem:

  1. Use specific dependency coordinates instead of wildcarded versions like 1.+ (which is best practice IMO)

  2. Update the repositories.[maven|ivy].metadataSources configuration. In Gradle 5.X the defaults were:

    repositories {
        maven {
            url "http://repo.mycompany.com/repo"
            metadataSources {
                mavenPom()
                artifact()
            }
        }
        ivy {
            url "http://repo.mycompany.com/repo"
            metadataSources {
                ivyDescriptor()
                artifact()
            }
        }
    }
    

    But in Gradle 6.0 they are now:

    repositories {
        maven {
            url "http://repo.mycompany.com/repo"
            metadataSources {
                mavenPom()
            }
        }
        ivy {
            url "http://repo.mycompany.com/repo"
            metadataSources {
                ivyDescriptor()
            }
        }
    }
    

    So to revert back to previous behavior, add the artifact() configuration to the repositores.[maven|ivy].metadataSources config block.

like image 145
Andy Guibert Avatar answered Sep 21 '22 09:09

Andy Guibert