Gradle with a local pom dependency picks up wrong version - gradle

My build.gradle references a local maven pom. I have enabled the mavenLocal() repository and have added the jar as a compile time dependency (eg. my-local-lib, as shown below).
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile (group: 'com.company', name: 'my-local-lib', version: '1.0-SNAPSHOT')
}
Gradle indeed picks it up and adds it as a dependency. My-local-lib, however, is itself dependent on another library as specified in its pom.xml, but gradle fails to pick up the correct version specified in the pom.xml, and instead chooses a much earlier version. This particular jar dependency is not a dependency on any other library.
Is this a known issue? Could it be due to my-local-lib being a SNAPSHOT version? Is there a way that I can enforce gradle to respect the versions specified in the libraries?

Try to add the following piece of code:
configurations.all {
resolutionStrategy {
cacheChangingModulesFor 0, 'seconds'
}
}
to build.gradle script.

Related

Gradle Dependency Problem when Upgrading to Gradle 6

I have a gradle Project where I have a dependency on "hudson-core 3.3.3"
compile group: 'org.eclipse.hudson', name: 'hudson-core', version: '3.3.3'
This works without a problem when using Gradle 5.6.2
When I upgrade to Gradle 6.0.1 I receive the following error:
Could not resolve org.eclipse.hudson:hudson-remoting:3.0.3.
Required by:
project : > org.eclipse.hudson:hudson-core:3.3.3
project : > org.eclipse.hudson:hudson-core:3.3.3 > org.eclipse.hudson:hudson-cli:3.3.3
> Could not resolve org.eclipse.hudson:hudson-remoting:3.0.3.
> inconsistent module metadata found. Descriptor: org.eclipse.hudson:hudson-remoting:3.0.4-SNAPSHOT Errors: bad version: expected='3.0.3' found='3.0.4-SNAPSHOT'
The Repository is always the same:
repositories {
mavenCentral()
maven {
url 'http://repo.jenkins-ci.org/public/'
}
}
Any Ideas why this error happens?
As said by #ToYonos, the problem is in the dependency itself.
Not perfect solutions, but 2 workarounds can be done as explained in Gradle's documentation (v6.7.1):
Exclude that transitive dependency, for example in the current Gradle versions using implementation instead of compile:
implementation('org.eclipse.hudson:hudson-core:3.3.3') {
exclude group: 'org.eclipse.hudson'
exclude module: 'hudson-remoting'
}
Override that transitive dependency version:
implementation('org.eclipse.hudson:hudson-remoting') {
version {
strictly '3.0.2' // As 3.0.3 is having the issue
}
}
In the pom.xml file of hudson-remoting 3.0.3, the version is <version>3.0.4-SNAPSHOT</version>
The issue is quite clear.
I tried with an old Gradle 4.4.1 and I am having the exact same issue. Likewise with Gradle 5.1.1 and your version, 5.6.2
I'm quite sure that if you clean your artefact cache for Gradle 5.6.2, it won't work anymore.
The error is on the repository side.
Another option is to define a repository that will download only a jar:
repositories {
mavenCentral() {
name = "Download only jar repo"
metadataSources { artifact() }
content {
// Use this repository only for org.eclipse.hudson:hudson-remoting
includeVersion("org.eclipse.hudson", "hudson-remoting", "3.0.3")
}
}
mavenCentral()
}
Also since pom is not downloaded you would have to add hudson-remoting dependencies by hand to build.gradle. But luckily for this particular case hudson-core already contains the only dependency commons-codec:commons-codec:1.4 that hudson-remoting needs, so this is not needed.
Note: the order of repositories is important, although in that case it will work either way. If you don't want to care about the order when using repositories with filter check exclusive content filtering.

how to declare dependency version in one place for many gradle projects

I work on a project with multiple grails services, plugins and libraries, all built with gradle with their dependencies declared in build.gradle files, one per project, this makes sense, I hope.
In maven I used to be able to declare versions of all dependencies in one parent project pom, or a pom template, and only include the dependencies in the projects that required them without the versions. This made upgrading dependencies easy in one place. Is there a simple way to do this in gradle?
Pseudocode example:
master_template/build.gradle
dependencies {
joda-time:joda-time:2.9.1
cglib:cglib:3.2.9
javax.servlet:javax.servlet-api:3.1.0
}
service_a/build.gradle
parent: master_template
dependencies {
joda-time:joda-time
javax.servlet:javax.servlet-api
}
service_b/build.gradle
parent: master_template
dependencies {
cglib:cglib
javax.servlet:javax.servlet-api
}
You can create a multi module project like you would do in maven with a parent pom.
In order to manage the dependency in the parent, I use the spring dependency management plugin.
You parent build.gradle would look like:
subprojects {
apply plugin: "io.spring.dependency-management"
sourceCompatibility = 1.8
targetCompatibility = 1.8
check.dependsOn dependencyCheckAggregate
repositories {
mavenLocal()
jcenter()
// other repos
}
dependencyManagement {
def jacksonVersion = "2.+"
dependencies {
dependency "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
dependency "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
dependency "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
dependency "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion"
dependency "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jacksonVersion"
}
}
}
Now, you can add dependencies to your submodules without specifying version.
You can easily achieve what you want by using Gradle's default apply from: 'other.gradle', so no additional plugins are needed.
In my micro-service project I'm using something like that:
common-gradle/env.gradle
apply plugin:'groovy'
ext.compile = [ 'joda-time:joda-time:2.9.1', 'cglib:cglib:3.2.9` ]
ext.testCompile = [ 'org.spockframework:spock-core:1.3-groovy-2.5' ]
common-gradle/dependencies.gradle
dependencies {
compile ext.compile
testCompile ext.testCompile
}
And the usage
service_a/build.gradle
apply from:'../common-gradle/env.gradle'
ext.compile << 'ch.qos.logback:logback-classic:1.2.3'
apply from:'../common-gradle/dependencies.gradle'
Thus each of my build.gradle files contain only 3-5 lines of critical information like project name and version.
You don't need to import the common-gradle as a project in your IDE, you can simply use symlinks to avoid using external references. Also during build on a Jenkins-like pipeline, the only thing you have to do is to check out the common-gradle repo into your working dir.

How Do We Run a Gradle Dependency Report for Plugins?

Running gradle dependencies lists compile-time dependencies. IOW, it reports direct and transitive dependencies coming from the dependencies closure for the subproject.
What is the equivalent means of determining the transitive dependencies being used by Gradle plugins, the ones specified by the dependencies closure in the buildscript closure?
For example, suppose I have this top-level build.gradle file in an Android project:
buildscript {
repositories {
jcenter()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.apollographql.apollo:gradle-plugin:0.3.1-SNAPSHOT'
}
}
allprojects {
repositories {
jcenter()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
}
How do I find out what transitive dependencies are being pulled in by the com.apollographql.apollo:gradle-plugin:0.3.1-SNAPSHOT dependency?
Gradle provides various help tasks. A list of them is available via gradle tasks -all.
To access the buildscript dependencies, one can use the gradle buildEnvironment command, as described in the Gradle docs:
4.7.5. Listing project buildscript dependencies
Running gradle buildEnvironment visualises the buildscript dependencies of the selected project, similarly to how gradle dependencies visualises the dependencies of the software being built.
As addition, CommonsWare stated, that the command must be executed from the project directory.

How to ignore bad pom 'inconsistent module descriptor' (version)

I need a dependency which has an inconsistent version number in it's pom.
Apache XmlSchema-Pom has as version SNAPSHOT which is obviously not correct as it should be 1.1.
According to this gradle discussion it should be possible if the maven repository specified as an ivy repo, adding #jar or transitive = false to the dependency, all that didn't work for me
Here my build.gradle with my attempts:
group 'de.company'
version '1.0-SNAPSHOT'
apply plugin: 'maven'
apply plugin: 'java'
repositories {
// specified as ivy repo
// ivy {
// url = mavenCentral().url
// }
mavenCentral()
}
dependencies {
// with #jar and transitive
// compile (group: 'org.apache.ws.commons', name: 'XmlSchema', version: '1.1', ext: 'jar') {
// transitive = false
// }
compile group: 'org.apache.ws.commons', name: 'XmlSchema', version: '1.1'
}
Here is the error message which gradle outputs:
Could not resolve all dependencies for configuration ':compileClasspath'.
> Could not resolve org.apache.ws.commons:XmlSchema:1.1.
Required by:
de.company:gradle-test:1.0-SNAPSHOT
> Could not resolve org.apache.ws.commons:XmlSchema:1.1.
> inconsistent module metadata found. Descriptor: org.apache.ws.commons:XmlSchema:SNAPSHOT Errors: bad version: expected='1.1' found='SNAPSHOT'
The way i solved this is different, I don't want to touch artifactory pom as i don't have access to artifactory. here is the code you need in gradle.build
repositories {
maven {
url 'http://xxxxx/xx'
metadataSources {
artifact() //Look directly for artifact
}
}
}
As to the current date, there is no actual way of ignoring the validating of the poms from gradle.
Still there are some ways to workaround that.
Try use an other version of that dependency, where the pom is valid
Check other repositories, maybe they have an valid pom for the depedency you want.
that would be in my example for XmlSchema the jcenter repository (XmlSchema from jcenter)
Download the sources by yourself and deploy it into your local/company repository and use this version instead

Gradle NoClassDefFoundError in jar dependency

I have developed a custom Gradle plugin and assembled as jar. This plugin has one dependency:
plugin/build.gradle
dependencies {
compile 'com.jcraft:jsch:0.1.53'
}
I have included my plugin in another consumer project (as jar in libs):
consumer/build.gradle
apply plugin: 'gg-release-plugin'
buildscript {
repositories {
flatDir {
dirs 'libs'
}
mavenCentral()
}
dependencies {
classpath 'com.myplugin.plugin:myplugin:1.0'
}
}
Everything works fine, but when code that uses classes of the dependency com.jcraft:jsch:0.1.53 is executed, I get an error:
java.lang.NoClassDefFoundError: com/jcraft/jsch/JSch
What am I doing wrong? How can I include the dependencies in jar file?
Seems, you've created a plugin jar library with compile time depnedency, that is not included anywhere in your final jar.
You can try to create your plugin jar as a fat jar, using Gradle FatJar plugin or something else. In that case, you'll have a single jar with all the dependent classes inside. But this could lead to problems, if someone will use the same library.
Or you can try to provide a JSch library together with your plugin jar and make a consumer build script dependency like:
buildscript {
repositories {
flatDir {
dirs 'libs'
}
mavenCentral()
}
dependencies {
classpath 'com.myplugin.plugin:myplugin:1.0'
classpath 'com.jcraft:jsch:0.1.53'
}
}
As I know, if you use a Maven repo to publish your plugin, you can provide a pom.xml to describe all the plugin's dependencies, but as I see, you are using a flatDir for it, so, it seems not to be possible.

Resources