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.
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.
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.
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' } }
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' }
Gradle supports different strategies to resolve the version conflicts scenarios, they are as follows:
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
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.
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
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.
18.224.56.29