Dependency resolution

We have seen the standard way of defining dependency and repository, which can help you to quick start with the concepts. It's time for a deep dive, and understand how to customize the standard configuration, which can suit your specific requirements.

Transitive dependency

Suppose your application depends on commons-httpclient-3.1.jar, which is a first-level dependency. However, this JAR again depends on the following other JARs, commons-codec-1.2.jar and commons-logging-1.0.4.jar.And if we try to find more details, commons-logging jar again depends on some other JARs.

Here, commons-httpclient-3.1 is a first-level dependency; the two previously mentioned JARs are second-level dependencies, and so on. However, with Gradle, you do not need to manage all these levels of dependencies. Imagine the complexity, if you have to figure out and mention each level of dependency in the build file. This can be very tedious and time consuming. And it becomes more painful if you encounter some version conflicts.

With Gradle, you do not need to bother about any such dependency-related issues. Gradle provides complete automation for the dependency management. You just define the first-level dependency and Gradle will take care of all the transitive dependencies. By default, it will download all the transitive dependencies until the last level.

Exclude transitiveness

For some scenarios, you might not want to depend on Gradle to fetch all transitive dependencies. Rather, you want to have complete control to download only the libraries that you have mentioned in the build file. To switch off a transitive feature, you can set the transitive flag off in the build file (build_transitive.gradle):

apply plugin:'java'
repositories {
  mavenCentral()
}
dependencies {
  compile group:'commons-httpclient', name:'commons-httpclient', version:'3.1', transitive: false
}

Clean the Gradle cache (~/.gradle/caches) and try to build the project again. This time it will download only one JAR that is commons-httpclient-3.1.jar:

$ gradle –b build_transitive.gradle build
…..
:compileJava
Download https://repo1.maven.org/maven2/commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.pom
Download https://repo1.maven.org/maven2/commons-httpclient/commons-httpclient/3.1/commons-httpclient-3.1.jar
:processResources UP-TO-DATE
…….

This feature could be useful if you need some other version of second-level dependencies, or the second-level dependency is missing in the repository and you want to manually copy that.

Selective exclude

There might be a scenario when you want to partially use transitive feature, that is, you do not want to stop Gradle from getting transitive dependencies, but you know it might result in a version conflict. So, you might want some specific jars to be excluded from the second or next-level of dependencies. To selectively exclude dependencies from the second-level onwards, you can use the following configuration:

dependencies{
  compile('commons-httpclient:commons-httpclient:3.1') {
    exclude group:'commons-codec' // exclude by group
    // exclude group:'commons-codec',module:'commons-codec'
  }
}

Tip

The exclude criteria requires group as the mandatory field, but the module can be optional.

Version conflicts

Version conflict is a very common scenario in which the project depends on a specific JAR but of different versions. For example, your project depends on commons-httpclient-3.1 JAR and commons-codec-1.1 JAR. The commons-httpclient-3.1 JAR has a transitive dependency on the commons-codec-1.2 JAR. During the build process, Gradle will find the dependency on two different versions of the same JAR. Your build file (build_versionconflict.gradle) will look like this:

apply plugin:'java'

repositories {
  mavenCentral()
}
dependencies {
  compile group:'commons-httpclient', name:'commons-httpclient', version:'3.1'
  compile group:'commons-codec',name:'commons-codec', version:'1.1'
}

Note

Issues due to version conflicts take a considerable amount of time even to get noticed.

Gradle supports different strategies to resolve the version conflicts scenarios, they are as follows:

  • Latest version: By default Gradle applies the get latest strategy to resolve version conflicts issues if it finds different versions of the same JAR file. In the preceding scenario, it will skip version 1.1 and download the commons-codec JAR of version 1.2.

    After executing the gradle –b build_versionconflict.gradle clean build command, the output will be as follows:

    Download https://repo1.maven.org/maven2/commons-codec/commons-codec/1.1/commons-codec-1.1.pom
    Download https://repo1.maven.org/maven2/commons-codec/commons-codec/1.2/commons-codec-1.2.pom
    ......
    Download https://repo1.maven.org/maven2/commons-codec/commons-codec/1.2/commons-codec-1.2.jar
    :processResources UP-TO-DATE
    ......
    
    BUILD SUCCESSFUL
    
  • fail on conflict: The Get latest strategy might not work always. Sometimes, rather than getting the latest version, you might want the build to fail for further investigation. To enable this, you apply the failOnVersionConflict() configuration by adding the following closure:
    configurations.all {
    resolutionStrategy {
      failOnVersionConflict()
    }
    }

    You can update your build file with the preceding configuration. If you want this strategy for all the builds, you can add this to your init script.

  • Force specific version: In conflict situations, another alternative could be, rather than failing the build, you can download specific version of a JAR. This can be achieved by using force flag:
    dependencies {
      compile group:'commons-httpclient', name:'commons-httpclient', version:'3.1'
      compile group:'commons-codec',name:'commons-codec', version:'1.1', force:true
    }

    Now, try to execute the gradle -b build_versionconflict.gradle build and observe the output:

    Download https://repo1.maven.org/maven2/commons-codec/commons-codec/1.1/commons-codec-1.1.pom
    Download https://repo1.maven.org/maven2/commons-codec/commons-codec/1.1/commons-codec-1.1.jar
    :processResources UP-TO-DATE
    :classes
    ….
    BUILD SUCCESSFUL
    

Dynamic dependency

To make the build flexible on the jar version, you can use the latest.integration placeholder, or you can define a version range such as 1.+. With this option, you do not have to stick to a specific version. With the 1.+ or 2.+ format, it will fix the major version to 1 or 2 (it could be any number) and it will pick the latest of the minor version (for example, 1.9 or 2.9).

compile group:'commons-codec',name:'commons-codec', version: '1.+'
compile group:'commons-codec',name:'commons-codec', version: 'latest.integration'

You can use either one to get the latest dependency.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.56.29