Maven doesn't locate dependecies in secondary mirrors - maven

I have a maven project with dependencies to the central repository and several to a local artifactory repository. When I try to run mvn rpm:rpm the dependencies related to the central repository are resolved, but those related to the local repository aren't.
My configuration looks like (schematically):
<mirrors>
<mirror>central</mirror>
</mirrors>
<profiles>
<profile>
<repository>local-repo1</repository>
<repository>local-repo2</repository>
</profile>
</profiles>

Related

How can I configure GITLAB CI with NEXUS?

I want to create a pipeline with Gitlab CI to compile a maven project.
First, I create a .m2 folder in root of my project and I add the settings.xml config file.
My project look like :
Project
- module1
- module2
- module3
- pom.xml
- .m2
-setting.xml
In the settings file I do this :
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd"
xmlns="http://maven.apache.org/SETTINGS/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<servers>
<server>
<id>nichefactory-releases</id>
<username>user</username>
<password>password</password>
</server>
<server>
<id>nichefactory-snapshots</id>
<username>user</username>
<password>password</password>
</server>
</servers>
<profiles>
<profile>
<id>nexus</id>
<properties>
<env>dev</env>
<flex.debug>true</flex.debug>
</properties>
<repositories>
<repository>
<id>nichefactory</id>
<name>NicheFactory Repository</name>
<url>http://my-nexus:8081/nexus/content/groups/public</url>
</repository>
</repositories>
</profile>
</profiles>
</settings>
In my pom.xml I have this repository :
<distributionManagement>
<!-- Publish the versioned releases to nexus -->
<repository>
<id>nichefactory-releases</id>
<name>Niche Factory Repository (RELEASE)</name>
<url>http://my-nexus:8081/nexus/content/repositories/releases</url>
</repository>
<!-- Publish the snapshot release to nexus -->
<snapshotRepository>
<id>nichefactory-snapshots</id>
<name>Niche Factory Repository (SNAPSHOTS)</name>
<url>http://my-nexus:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
And in my .gitlab-ci.yml I have :
image: maven:latest
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
build:
stage: build
script:
- mvn compile -P dev -DskipTests
When I push this config to gitlab, the pipeline start with a failure message :
Failure to find apps:pom:version in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced and 'parent.relativePath' points at wrong local POM # line 4, column 10
It seems that gitlab try to connect to the default maven repository and not to my nexus.
How can I tell gitlab to call the nexus repository and not the default repository ?
MAVEN_CLI_OPTS is not an official MAVEN environment variable, but the recommended way to store repeating options. you can even see this in the GitLab Example
Just try:
build:
stage: build
script:
- mvn $MAVEN_CLI_OPTS compile -P dev -DskipTests

Maven multiple repositories - jcenter, nexus

I am trying to set up maven with 2 repositories - jcenter & nexus. From nexus, we don't have the ability to proxy to jcenter. Hence I need a set up which can do the following-
If a artifact is found in nexus, download it.
If not found, go to jcenter to download artifact.
With the below settings.xml, it seems like maven only tries to download from central (which is set to bintray here, because its a super set of maven central). How can I tell maven to look in central and nexus?
Note- I have tried <mirrorOf>central, !nexus</mirrorOf>
<mirrors>
<mirror>
<id>bintray</id>
<name>bintray</name>
<url>http://jcenter.bintray.com</url>
<mirrorOf>central</mirrorOf>
</mirror>
<mirror>
<id>nexus</id>
<mirrorOf>!bintray, *</mirrorOf>
<url>http://some/url/goes/here</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>allow-snapshots</id>
<activation><activeByDefault>true</activeByDefault></activation>
<repositories>
<repository>
<id>jcenter</id>
<url>http://jcenter.bintray.com</url>
</repository>
</repositories>
</profile>
</profiles>
I got it working by specifying multiple repo's in my parent pom. multiple repos in settings.xml had no effect on maven.

Copy snapshot artifact from nexus without pom

I want to download a snapshot artifact using the dependecy.copy target. I don't want to have a POM file.
mvn -U dependency:copy -Dartifact=mygroupId:myArtifactId:myversion-SNAPSHOT:jar
Unfortunately this only works if the artifact is already in the local maven repo cache. When it's not in the maven cache I get the following error:
Unable to find artifact.
...
foo-public (https://nexus.foo.org/content/groups/public-foo/, releases=true, snapshots=false)
It says foo-public because I'm using a settings.xml
<mirror>
<id>foo</id>
<mirrorOf>*</mirrorOf>
<name>My Maven Nexus Repository</name>
<url>http://nexus.foo.org/content/groups/public-foo/</url>
</mirror>
The reason seems to be that Maven's Super POM has set snapshots=false for the central repo. If I add a minimalistic pom.xml to the working directory I don't have the error as snapshots=true seems to be the default for any other repo.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>dummy</groupId>
<artifactId>dummy</artifactId>
<version>1</version>
<repositories>
<repository>
<id>dummy</id>
<url>dummy</url>
</repository>
</repositories>
</project>
My current work around is to write the dummy POM before calling my mvn command. Another possible work around is to add the following to settings.xml (Found in Sonatype nexus book)
<profiles>
<profile>
<id>nexus</id>
<!--Enable snapshots for the built in central repo to direct -->
<!--all requests to nexus via the mirror -->
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
Do you have a more elegant idea that works without so much preparation? For instance a command line switch?
One solution is to use dependency:get goal instead of dependeny:copy goal, see Apache Maven Dependency Plugin:
The dependency:get Mojo
This mojo is used to fetch an artifact and (optionally) its dependencies from remote repositories using its Maven coordinates.
mvn dependency:get -DgroupId=org.apache.maven -DartifactId=maven-core -Dversion=2.2.1 -Dpackaging=jar -Dclassifier=sources -DremoteRepositories=central::default::http://repo1.maven.apache.org/maven2,myrepo::::http://myrepo.com/maven2
mvn dependency:get -DgroupId=org.apache.maven -DartifactId=maven-core -Dversion=2.2.1 -Dpackaging=jar -Dclassifier=sources -DremoteRepositories=http://repo1.maven.apache.org/maven2
mvn dependency:get -Dartifact=org.apache.maven:maven-core:2.2.1:jar:sources -DremoteRepositories=http://repo1.maven.apache.org/maven2 -Ddest=/tmp/myfile.jar
Your modified command:
mvn dependency:get -U -DgroupId=mygroupId -DartifactId=myArtifactId -Dversion=myversion-SNAPSHOT -Dpackaging=jar -Dtransitive=false -s settings.xml -DremoteRepositories=https://nexus.foo.org/content/groups/public-foo/ -Ddest=target/myArtifactId.jar

Using multiple Maven mirrors to pull different jar version into a project

I am experiencing issues pulling in a new version of a library which lives in a different repository. I believe I have to update my settings.xml and my parent level pom.xml which specifies the new version.
Currently my settings.xml reads like the following:
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<url>http://serenity.gm.edu/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
<mirror>
<id>mods</id>
<url>http://7.169.72.8:8081/nexus/content/repositories/releases/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>default</id>
<repositories>
<repository>
<id>mod-thirdparty</id>
<url>http://7.169.72.8:8081/nexus/content/repositories/thridparty/</url>
</repository>
<repository>
<id>mod-snapshots</id>
<url>http://7.169.72.8:8081/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
</profile>
</profiles>
<servers>
<server>
<id>Tomcat</id>
<username>admin</username>
<password>xxx</password>
</server>
</servers>
The default mirror where everything gets pulled in from is serenity. I am trying to pull in a custom library mod3.2 from 7.169.72.8 but version 2.3 keeps getting pulled in from serenity. I have tried a number of <mirrorOf> settings such as *,!central with no success.
My parent pom.xml is fairly straightforward defining a list of modules, proerties, and global dependencies. Here are the items of interest (it is too long to show).
<project ...>
...
<distributionManagement>
<repository>
<id>releases</id>
<name>mod2-releases</name>
<url>http://7.169.72.8:8081/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>mod2-snapshots</name>
<url>http://7.169.72.8:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<properties>
...
<mod2.version>3.2</mod2.version>
...
</properties>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mod2.commons</groupId>
<artifactId>mod2.commons.lang</groupId>
<version>${mod2.version}</version>
</dependency>
<dependency>
<groupId>mod2.commons</groupId>
<artifactId>mod2.commons.audit</groupId>
<version>${mod2.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
To recap - I'm trying to get version mod2 version 3.2 from 7.169.72.8 but all I can pull in mod2 version 2.3 from the serenity repo. Thanks for any help.
In your configuration, you are declaring multiple mirrors for the Central repository. However, Maven does not support that:
Note that there can be at most one mirror for a given repository. In other words, you cannot map a single repository to a group of mirrors that all define the same value. Maven will not aggregate the mirrors but simply picks the first match. If you want to provide a combined view of several repositories, use a repository manager instead.
In your case, Maven is picking the first mirror of Central, which is of id nexus, and ignoring the second one, which is of id mods. Therefore, when fetching for your artifact, it only searches nexus and fails to find it.
There are a couple of solutions:
If you really want to have multiple mirrors for the same repository, you will need to use a repository manager and configure this on the repo manager itself.
It's not clear why you need to mirror Central and point to 7.169.72.8:8081 if this repository doesn't have all the artifacts needed to make your build work. If the rest are hosted on serenity.gm.edu, you could host all of them on serenity.gm.edu.
You could also not use the mods mirror at all. Let serenity.gm.edu be the mirror for Central and just declare a new repository that isn't Central to fetch your artifacts. You already declared the mod-thirdparty and mod-snapshots repositories, so this is a matter of activating the profile they are under with:
<activeProfiles>
<activeProfile>default</activeProfile>
</activeProfiles>
in the settings.xml. With this, Maven will also look for your artifacts at the URL configured for those repo (and those are not mirrored by nexus).

which repository will maven choose inside settings.xml

If I define two repositories in my settings.xml, which repositories will maven choose during build?
Like below, codehausSnapshots1 or codehausSnapshots2 ?
<profiles>
<profile>
<repositories>
<repository>
<id>codehausSnapshots1</id>
......
<repository/>
<repository>
<id>codehausSnapshots2</id>
......
<repository/>
</repositories>
</profile>
</profiles>
It is using both of them. There is a certain order which repository maven looks first, what next and so on. If Maven fails to download artifact from the first repo, it will try download it from the next repo. Maven looks repositories first from settings.xml, then project's pom.xml and lastly parent pom's repositories. Also, order of declared repositories matter. In this example, maven looks codehausSnapshots1 repository first as it is declared before codehausSnapshots2.

Resources