Gradle - getting the latest release version of a dependency - java

What would be the easiest way to tell Gradle the following:
Retrieve 'junit' dependency and take its latest 'release' version.
Managing Maven and Ivy repositories is sort of new to me. I tried the following steps and they result in Could not resolve dependency ... error:
Write compile "junit:junit:latest.release" with repositories set to only mavenCentral() (however, it works if I say "junit:junit:4.10").
Write compile "junit:junit:latest.release" with repository set the following way:
ivy {
// I also tried 'http://maven.org' and other possible variants.
url "http://repo1.maven.org"
layout "maven"
}
Attempted to use Spring Source Ivy repository:
ivy {
artifactPattern "http://repository.springsource.com/ivy/libraries/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
ivyPattern "http://repository.springsource.com/ivy/libraries/release/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"
}
Maybe I misunderstand something. Why would getting the latest version of the dependency be such a hard task?

It can be quite useful sometimes to get the latest release - if for example you release often your own dependencies.
You can get the latest version like
compile "junit:junit:+"
or better specify at least the major version like
compile "junit:junit:4.+"

Gradle currently does not support Maven's RELEASE (which is rarely used and deprecated) but it does support Ivy's latest.release (and for snapshots latest.integration). However, the general recommendation is to build against exact versions. Otherwise, the build can become a lottery.

Check out the Gradle-Versions-Plugin. It does exactly what you want: https://github.com/ben-manes/gradle-versions-plugin
For the installation, see the github page. Basically you need to add these two lines to your build.gradle - project file:
apply plugin: 'com.github.ben-manes.versions'
buildscript {
[...]
dependencies {
classpath 'com.github.ben-manes:gradle-versions-plugin:0.8'
[...]
}
}
[...]
Then you can use the plugin, by running this command in terminal in your project dir:
./gradlew dependencyUpdates -Drevision=release
And it will show you which dependencies are outdated!

Latest Gradle User Guide mentions and explains plus sign in versions:
From 7.2. Declaring your dependencies:
dependencies {
compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.7.Final'
testCompile group: 'junit', name: 'junit', version: '4.+'
}
... The build script also states that any junit >= 4.0 is required to compile the project's tests.
From 23.7. How dependency resolution works:
If the dependency is declared as a dynamic version (like 1.+), Gradle will resolve this to the newest available static version (like 1.2) in the repository. For Maven repositories, this is done using the maven-metadata.xml file, while for Ivy repositories this is done by directory listing.

In Android Studio:
If you're using + for the version, and want to know which version is actually being used, select Project in the sidebar, and then under External Libraries you will see the actual version number in use.

Another similar notation for Kotlin DSL (build.gradle.kts):
dependencies {
implementation("or.jsoup", "jsoup") {
version {
require("1.14.+")
}
}
// OR simply
// implementation("or.jsoup:jsoup:1.14.+")
}
Read more about this in Gradle documentations.
An excerpt from the docs:
A dynamic version can be either a version range (e.g. 2.+) or it can be a placeholder for the latest version available e.g. latest.integration.

Related

Dependency version not resolved from ext block build.gradle

I have added some dependency in my build.gradle file like this
ext {
boxableVersion = '1.5.bq'
}
dependencies {
implementation group: "com.github.dhorions", name:'boxable', version:${boxableVersion}
}
This was working seamlessly until I changed my JDK version from 1.8 to 11. Now, When I am trying to build the project, the following error shows up in my build.gradle file
Could not run phased build action using Gradle distribution 'https://services.gradle.org/distributions/gradle-6.0-bin.zip'.
Build file '/home/christine/christine/projectsFromGit/pdfcreator/build.gradle' line: 43
A problem occurred evaluating root project 'pdfcreator'.
Could not find method $() for arguments [build_4fl1snfk49qgbmumnf1gg989h$_run_closure3$_closure11#d7c9f2a] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
If i give version directly like this, the project is building successfully
implementation group: "com.github.dhorions", name:'boxable', version:'1.5.bq'
How can i give versions externally like I was doing before?
The following syntax version:${boxableVersion} in your dependency declaration is not valid. It's not related to your JDK version, it's just that ${...} means nothing in Gradle DSL or Groovy syntax.
If you want to define version in an 'ext' property, you can then reference this property directly with version: boxableVersion (ext properties are made available directly in the script through the "groovy magic"), or you can use Groovy String interpolation notation (please note the double-quote ")
version: "${boxableVersion}"
Or , in a simpler way:
implementation "com.github.dhorions:boxable:${boxableVersion}"
Just try:
ext {
boxableVersion = '1.5.bq'
}
dependencies {
implementation group: "com.github.dhorions", name:'boxable', version:"${boxableVersion}"
}

Plugin was not found with building gradle

Having a gradle project.
When i'm trying to build project.
buildscript {
ext {
springBootVersion = '2.2.4.RELEASE'
}
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath "gradle.plugin.org.hidetake:gradle-swagger-generator-plugin:2.9.0"
classpath "net.ltgt.gradle:gradle-apt-plugin:0.21"
}
}
plugins {
id "net.ltgt.apt-eclipse" version "0.21"
id "net.ltgt.apt-idea" version "0.15"
id "net.ltgt.apt" version "0.15"
}
I have error which is connected with plugins
Plugin [id: 'net.ltgt.apt-eclipse', version: '0.15'] was not found in any of the following sources:
How to fix it?
I was facing the same issue. In build.gradle, the paths provided for the dependencies weren't matching the folders specified. Placing the folders in the mentioned path shown in the build.gradle solved it. After that I was able to build the project without errors.
TL;DR: If you are using a current gradle version, it's fine to just drop all of the net.ltgt.apt dependencies. You will not need it anymore because, it's features are now available natively in Gradle.
More details:
From the plugin README.md (https://github.com/tbroyer/gradle-apt-plugin#readme)
The goal of this plugin was to eventually no longer be needed, being superseded by built-in features. This has become a reality with Gradle 5.2 and IntelliJ IDEA 2019.1. tl;dr: this plugin is obsolete, don't use it. If you're using Eclipse though, continue reading.
It originally did a few things to make it easier/safer to use Java annotation processors in a Gradle build. Those things are now available natively in Gradle, so what's this plugin about?
If you use older versions of Gradle (pre-4.6), you can still benefit from those features:
it ensures the presence of configurations for your compile-time only dependencies (annotations, generally) and annotation processors, consistently across all supported Gradle versions;
automatically configures the corresponding JavaCompile and GroovyCompile tasks to make use of these configurations, when the java or groovy plugin is applied.
With recent versions of Gradle (between 4.6 and 5.1), this plugin will actually only:
add some DSL to configure annotation processors; it is however recommended to directly configure the tasks' options.compilerArgs;
backport the sourceSet.output.generatedSourcesDirs Gradle 5.2 API;
configure JavaCompile and GroovyCompile tasks' options.annotationProcessorGeneratedSourcesDirectory with a sane default value so you can see the generated sources in your IDE and for debugging, and avoid shipping them in your JARs.

Gradle find wrong maven repository url in eclipse

this is my build.gradle
repositories {
mavenCentral()
maven{url 'http://example.com/repository/maven-public/'}
}
dependencies {
compile group: 'com.example', name: 'example-commlib', version: '1.0'
}
and the link http://example.com/repository/maven-public/ is build from Nexus Repository Manager which can accessable.
and when I click Refresh Gradle Project in eclipse.
I can see the link is point to
https://repo.maven.apache.org/..../example-commlib-1.0.pom
I think the right url is
http://example.com/repository/maven-public/.../example-commlib-1.0.pom
I've check the gradle setting and maven setting in eclipse. It seems fine.
So what's the problem?
Do you have other dependencies on this project? It is possible that the "pom.xml" file of one of the packages you are pulling references example-commlib as a dependency and has the Apache Maven URL hardcoded, and resolves the URL beforehand. You can use gradle dependencies to show the dependency tree and find which version is affected. The answers in this post have suggestions on how to force a specific dependency as well: How can I force Gradle to set the same version for two dependencies?

How to put local dependencies first when calling gradle idea?

When calling gradle idea, external dependencies are ordered first in the class path relatively to local Jar inclusions. As such :
dependencies {
compile fileTree(dir: 'libs', include:['*.jar'])
compile group: 'foo', name:'bar', version:'1.0.0'
}
will include my local jars last. This is a problem in my project as these jars' purpose is to partially overwrite the external library.
The same behavior is observed when specifying the repository as a source of dependencies using flatDir and loading the jar without fileTree. It is put last in the classpath.
I have found several mentions of the problem when researching, such as https://discuss.gradle.org/t/gradle-messes-up-the-classpath-order-in-generated-projects-when-there-are-mixed-dependency-types/13130, but no workarounds.
I suppose these exist, gradle being very customisable, but being very new to it my attempts to make one fail. How to proceed?
I'm not using IntelliJ on a regular basis but tried it in the context of this question and my impression is that gradle's idea plugin and IntelliJ's gradle plugin don't go well together. That is you should either use the idea gradle plugin and import as plain Java project or import as gradle project using IntelliJ's gradle plugin. Main reason is that the idea plugin and the IntelliJ plugin are generating slightly different iml-files (those files are holding the project dependencies - amongst others) which leads to lot of confusion when using both plugins together. As you specifically asked for the gradle idea plugin, I used this plugin and imported into IntelliJ as plain java project.
But to answer your question I found no evidence that the order of libraries on the classpath differs from the order as declared in the dependencies section of the gradle file, when using a flatDir repo. When using compile fileTree(dir: 'libs', include:['*.jar']) the order was actually broken as described in your question. That is, you should stick to using a flatDir repo.
I'm using gradle 4.9 and IntelliJ 2018.2.
This is my gradle file
apply plugin: 'java'
apply plugin: 'idea'
repositories {
jcenter()
flatDir {
dirs 'libs'
}
}
dependencies {
compile 'zzz:zzz-0.0.0'
compile 'aaa:aaa-0.0.0'
compile 'com.google.guava:guava:24.0-jre'
compile group: 'javax.websocket', name: 'javax.websocket-api', version: '1.1'
}
task wrapper(type: Wrapper) {
gradleVersion = '4.9'
distributionUrl = "http://services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip"
}
In my libs folder there are two jars aaa-0.0.0.jar and zzz-0.0.0.jar both are copies of guava-24.0-jre.jar. That is all guava classes are present in both jars as well. As zzz:zzz-0.0.0 is the first dependency in the gradle file, the expectation would be that guava classes are being loaded from zzz-0.0.0.jar instead of guava-24.0-jre.jar or aaa-0.0.0.jar. I used the following main class to test this:
package test;
import com.google.common.math.LongMath;
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(LongMath.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
}
And the output when running it from IntelliJ is
file:/C:/ws/gradle-idea-test/libs/zzz-0.0.0.jar
That is the com.google.common.math.LongMath class is indeed being loaded from the local libs/zzz-0.0.0.jar instead of the guava-24.0-jre.jar.
I noticed that the list of external dependencies in IntelliJ doesn't show the local libraries. And even more confusing the libraries are ordered alphabetically and don't reflect the actual order on the classpath which might be quite confusing:
To get the actual order of elements on the classpath you will have to look in the module dependencies section in the module settings ("Open Module Settings" > "Project" > "Modules" > "Dependencies Tab") which looks like this:
As you can see the dependencies are listed in correct order and include the local libraries as well. The order of libs in this dialog is basically the same as in the generated iml-file.
When using the IntelliJ gradle plugin instead of gradle's idea plugin, IntelliJ basically behaved the same way but the generated iml-file looked different and the external libraries were displayed in a different format. But there was no difference regarding the classpath order.

NoClassDefFoundError when using Guava classes even though Guava is included in Gradle build file and on classpath

When I build my Guava dependent project with Gradle using:
//build.gradle
plugins {
id 'java'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile group: 'com.google.guava', name: 'guava', version: '22.0'
}
task wrapper(type: Wrapper) {
gradleVersion = '3.3' //Tried 3.1 - 4.0.1
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}
I get the following runtime error when running the project in Intellij:
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/Multiset
The libraries are definitely in the classpath and I cannot figure out why this is happening.
I have solved this problem by switching to an older Gradle version (3.1, 3.2, 3.3 all work).
Therefore, I believe the problem lies with Gradle 3.4+ (3.4, 3.5.1, 4.0 and 4.0.1) all of which I have tried and received the NoClassDefFoundError.
There is no mention of a Gradle version required in the Guava documentation
Is Guava incompatible with newer versions of Gradle?
The reason behind such behavior lies in your classpath. Compile time classpath is different than classpath for runtime. You pass guava to javac but you don't have it available at runtime.
Very good explanation of quite a similar issue is here: NoClassDefFoundError at Runtime with Gradle. I can't reproduce this issue locally. Consider going to your gradle cache and remove everything.
The problem ended up being with the version of Intellij I was using (2016.3.1)
Once I updated Intellij to 2016.3.7 the project runs fine with all versions of Gradle.

Categories