Force Gradle To Resolve Snapshot Dependencies From Different Repo - gradle

In my build.gradle for a Java project, I have a list of Maven repositories I am pointing to for dependency resolution, as follows:
repositories {
maven {
url "https://artifactory.myco.com/artifactory/maven-us-east-1-local"
}
maven {
url "https://artifactory.myco.com/artifactory/maven_snapshots-us-east-1-local"
}
mavenCentral() }
It looks like the snapshots repo above barfs during resolution when gradle tries to see if a non-snapshot dependency lives there, as it goes through and contacts each repo in order. In artifactory it has been configured with a policy and it sends back a 409 conflict when it gets asked if it has a non-snapshot dependency. This is what I get:
./gradlew build
.
.
.
FAILURE: Build failed with an exception.
What went wrong:
Could not resolve all dependencies for configuration > 'com.myco.project:pgs_common:compile'.
Could not resolve mydep:mydep:1.0.9.
Required by:
com.myco.project:pgs_common:1.28.0-SNAPSHOT
Could not resolve mydep:mydep:1.0.9
Could not get resource 'https://artifactory.myco.com/artifactory/maven_snapshots-us-east-1-local/mydep/mydep/1.0.9/mydep-1.0.9.pom'.
Could not GET > 'https://artifactory.myco.com/artifactory/maven_snapshots-us-east-1-local/mydep/mydep/1.0.9/mydep-1.0.9.pom'. Received status code 409 from server: Conflict
Is there a way in gradle to tell it to not bother contacting that repo for non-snapshot dependencies? In Maven you can add extra properties in a repository declaration telling Maven whether it allows release dependencies, snapshot dependencies, or both (the default).
Thanks.

I have similar issues with Gradle 4.x and 5.x, the workaround is to use Gradle 2.x.
By using Gradle 2.x does not stop Gradle search non-snapshot libs from release repository, but at least Gradle can find decency.

Related

Gradle artifactory plugin not resolving JAR dependencies

I am upgrading my build to Gradle 7.4.2 running with Java 11 and use Artifactory as my repository. I am using the latest Gradle Artifactory Plugin and my builds are failing to resolve JAR dependencies now.
In Artifactory I'm using a virtual repository to resolve dependencies like Apache Commons Text as well as my own local collection of JARs that I've deployed to a separate Artifactory repository that is connected to the virtual repository.
My build was resolving my JAR dependencies fine under Gradle 5.6.4/Java8. Now my build fails with errors like this.
Resource missing. [HTTP GET: https://artifactory.myco.com:443/artifactory/collective-gradle-virtual/com/myco/a/myjni/2.5-AABBCC/myjni-2.5-AABBCC.pom]
Resource missing. [HTTP GET: https://artifactory.myco.com:443/artifactory/collective-gradle-virtual/com.myco.a/myjni/ivy-2.5-AABBCC.xml]
The final build error message said something similar:
> Could not find myco.com.a:myjni:2.5-AABBCC.
Searched in the following locations:
- https://artifactory.myco.com:443/artifactory/collective-gradle-virtual/com/myco/a/myjni/2.5-PH44157/myjni:2.5-AABBCC.pom
- https://artifactory.myco.com:443/artifactory/collective-gradle-virtual/com.myco.a/myjni/ivy-2.5-AABBCC.xml
Required by:
project :MyJAR
Is there some change between Gradle/the Gradle Artifactory Plugin/Java 11 such that the build can no longer resolve JAR artifacts?
I even tried creating a myjni-2.5-AABBCC.pom file and deployed it to the same path as the JAR. That fails too because the repository has the JAR and POM in com.myco.a and the resolver is looking for it in com/myco/a.
I also changed my dependencies to append #jar at the end in the hopes that would change the resolver behavior. It did not.
My dependency looks like this:
dependencies {
implementation 'com.myco.a:myjni:2.5-AABBCC#jar'
}
My artifactory block is this:
artifactory {
contextUrl = "https://artifactory.myco.com:443/artifactory"
resolve {
repository {
repoKey = 'collective-gradle-virtual'
username = "${artifactoryUser}"
password = "${artifactoryKey}"
maven = true
}
}
}
Update 1
I discovered that even though my existing setup worked fine before the upgrade, for some reason now, it requires a POM file to exist with the actual JAR. I also suspect that the use of dots in the group name is causing problems with locating the POM file. So I'm renaming those groups to not have dots.
UPdate 2
I restructured my repository to change the dotted group name in the repository to a maven-style directory tree and added a POM for each dependency. Now the dependencies resolve, but I don't understand why the behavior changed when I upgraded Java, Gradle and the Gradle Artifactory Plugin.

Unable to load Maven meta-data from private repo. Received 403: Forbidden

I'm trying append a private dependency into my project (react-native-android) via Maven. Unfortunately I'm get following error message when I try to build ./gradlew assembleDebug my project.
Error message returned as below:
> FAILURE: Build failed with an exception.
* What went wrong:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> Could not resolve all task dependencies for configuration ':app:debugCompileClasspath'.
> Could not resolve com.facebook.react:react-native:0.19.+.
Required by:
project :app > project :react-native-i18n
> Failed to list versions for com.facebook.react:react-native.
> Unable to load Maven meta-data from https://xxxPRIVATE_REPOxxx/android/com/facebook/react/react-native/maven-metadata.xml.
> Could not get resource 'https://xxxPRIVATE_REPOxxx/android/com/facebook/react/react-native/maven-metadata.xml'.
> Could not GET 'https://xxxPRIVATE_REPOxxx/android/com/facebook/react/react-native/maven-metadata.xml'. Received status code 403 from server: Forbidden
Code example
repositories {
mavenCentral()
maven {
url 'https://maven.google.com/'
name 'Google'
}
maven { url "https://xxxPRIVATE_REPOxxx/android" }
}
dependencies {
implementation project(':react-native-i18n')
implementation 'com.android.support:support-v4:+'
implementation 'xxxPRIVATE_DEPENDENCYxxx:1.0.+'
}
I have read numerous post and research on maven and gradle's topic. Here's my finding towards my issues:
Meaning that my sequence of declaring maven by right will get the "correct/suitable" module from the first declared maven instead of the following (maven xxxPRIVATE_REPOxxx)
The order of declaration determines how Gradle will check for dependencies at runtime. If Gradle finds a module descriptor in a particular repository, it will attempt to download all of the artifacts for that module from the same repository. You can learn more about the inner workings of dependency downloads.
Returning of 403 Forbidden does not necessary mean I do not have access to the repo I'm trying to access, but also missing of resource.
Hence I made an assumption here... During the download of project dependencies, Maven loop through both maven repo (maven google & xxxPRIVATE_REPOxxx) to get the suitable lib. However when it reaches xxxPRIVATE_REPOxxx, it failed to locate maven-metadata.xml therefore result with https://xxxPRIVATE_REPOxxx/android/com/facebook/react/react-native/maven-metadata.xml and 403 Forbidden.
My question:
Should there be a way to indicate which dependency to get from which Maven?
I was imaging something like this
implementation 'xxxPRIVATE_DEPENDENCYxxx:1.0.+' : xxxPRIVATE_REPOxxx (You know what I mean)
I have tried:
Upgrading my Android-Plugin to 3.5.0
Upgrading my Gradle version to 5.6.4
./gradlew clean and re-build after steps 1 and 2
Turns out the issue was because the react native dependencies use by 3rd party library (react-native-i18n) was too low. You can find it at react-native-i18n's build.gradle.
dependencies {
compile 'com.facebook.react:react-native:0.12.+'
}
Hence my fix to this was update the code to
compile 'com.facebook.react:react-native:+'

When does gradle store in .m2 and when in cache?

In which scenario will gradle store artifacts in the directory .m2 and in which scenario will it store them in gradle\caches?
I am trying to resolve my issue wherein I have a dependency within my local build
Gradle will read from your local maven repository only when you declare it as a valid repository:
repositories {
mavenLocal()
}
Gradle will write to your local maven repository only when you publish artifacts and tell it to publish to the local maven repo.
If you are using the maven plugin, when executing the task install
If you are using the maven-publish plugin, when executing the task publishToMavenLocal
Gradle will use its own internal cache for all resolved dependencies, including ones coming from the local maven repository.
For example, if you use a dependency org:foo:1.0 from your maven local repository, the metadata and artifact will be copied to the Gradle cache on first resolution. From then on, the dependency will be resolved from the Gradle cache.
However, if the dependency is changing, such as when using a -SNAPSHOT version, the Gradle cache will by default keep the last one resolved for 24h. After which it will perform a new resolution, hitting again the local maven repository in this example.
See the documentation for controlling that cache duration for dynamic and/or changing dependencies.

Why does gradle push a dependency to my maven repo while resolving dependencies?

This is my basic setup:
// Dependencies
repositories {
maven { url "http://MYREPO.." }
jcenter()
mavenLocal()
}
dependencies {
compile 'org.bytedeco.javacpp-presets:opencv:3.1.0-1.2'
}
From my understanding of how dependency resolution works, gradle should try and seek for the dependency first in my repo, then in jcentral() and then in mavenLocal.
Instead, I get this output on ./gradlew assemble:
:compileJava
Download http://MYREPO.../org/bytedeco/javacpp-presets/opencv/3.1.0-1.2/opencv-3.1.0-1.2.jar
:processResources UP-TO-DATE
:classes
:jar UP-TO-DATE
:assemble UP-TO-DATE
BUILD SUCCESSFUL
In fact, when I take a look inside my repository to see what happens, I found the opencv dependency being PUSHED as a consequence of the dependency resolution.
I would expect instead the artifact to be downloaded from jcenter, where it's in fact present.
I am using apache archiva.
Why does this happen?
Is this behaviour documented somewhere?
I don't undrstand if this is a problem with my repository settings or with the gradle script.
If your repository is mirroring the central repo, then what happens is this:
Gradle tries to find a dependency from your repo
Your repo does have it, so it contacts the upstream repo that it is mirroring
Dependency is downloaded from the upstream repo and is cached in your repo
Dependency is handed to Gradle
This never leaves Gradle the chance to try to contact jcenter directly :)
For Apache Archiva, the caching settings are configurable under "Proxy Connectors" and documented here:
http://archiva.apache.org/docs/1.4-M4/adminguide/proxy-connectors.html
You can basically choose how frequently (or not at all) to cache the artifacts from the mirrored repo for use in subsequent requests.

Gradle build fails because of Nexus returning 400 Bad Request

We have a company-wide Nexus 3 server which
hosts our own artifacts and
is used as proxy to Maven Central and other repos.
The developers use two repositories:
maven-releases for all released/stable artifacts with the version policy "Release" and
maven-snapshots for all snapshots artifacts with the version policy "Snapshot".
Both repositories are used in a Gradle build:
repositories {
maven {
name "snapshots"
url "http://nexus3.server:8081/repository/maven-snapshots"
}
maven {
name "releases"
url "http://nexus3.server:8081/repository/maven-releases"
}
}
Now when Gradle tries to resolve a snapshot-dependency it asks the releases-repository, Nexus answers with
Error 400 Bad Request
Repository version policy: RELEASE does not allow version: 1.0-SNAPSHOT
and the build fails with
> Could not resolve group.id:artifact-id:1.0-SNAPSHOT.
Required by:
:my-project:unspecified
> Could not resolve group.id:artifact-id:1.0-SNAPSHOT.
> Could not get resource 'http://nexus3.server:8081/repository/maven-releases/group/id/artifact-id/1.0-SNAPSHOT/artifact-id-1.0-SNAPSHOT.pom'.
> Could not GET 'http://nexus3.server:8081/repository/maven-releases/group/id/artifact-id/1.0-SNAPSHOT/artifact-id-1.0-SNAPSHOT.pom'. Received status code 400 from server: Bad Request
How do I need to configure Gradle so that this error is ignored and the next repository ("snapshots") is tried? Or is it possible to configure Nexus to return 404 Not Found instead of 400 Bad Request?
Version: Gradle 2.9
Check out the Nexus Repository Manager 3 documentation for gradle usage as well as the example projects. That should show you how to use a init.gradle for downloading from the repository group.
RaGe's comment was a good hint: The dependency was neither in snapshots nor in releases but in a third repository which I was not aware of. After adding the third repository to Gradle the dependency was resolved.
One other issue I found while uploading a build:
Make sure you don't have -SNAPSHOT on your version name while uploading to Staging!
-SNAPSHOT versions are not accepted.

Resources