Maven multiple repositories - jcenter, nexus - maven

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.

Related

doesnot use the provided mirror in settings.xml

I need to download a dependency "proxy-vole" from maven and it is present on "https://artifacts.alfresco.com/nexus/content/groups/public"
So I have mentioned the above url as mirror in my setting.xml in maven but everytime I run the project from maven ,it tries to download the jar file from other url (mirror 2) where this depency doesnot exists. and i get error.
my setting.xml is :
<mirrors>
<mirror>
<id>maven.alfresco</id>
<mirrorOf>alfresco-public</mirrorOf>
<name>alfresco artifacts repository</name>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</mirror>
<mirror>
<id>FTRDProxy_central</id>
<mirrorOf>central</mirrorOf>
<name>FTRD Maven Proxy mirroring central (maven 2) repository</name>
<url>url for mirror2</url>
</mirror>
<mirror>
<id>maven.apache</id>
<mirrorOf>maven2</mirrorOf>
<name>Apache Maven Proxy mirroring central (maven 2) repository</name>
<url>https://repo.maven.apache.org/maven2</url>
</mirror>

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).

Is there such a thing as a local remote Maven repository?

I have a build box on which is installed:
Maven
Bamboo
Archiva
I have configured Bamboo to grab my Maven project from a remote Git source and then build it with the goals 'clean install'.
I have configured Archiva with two repos:
mirror - a mirror of central
dev - repo for my artifacts
I have made the following changes to Maven settings.xml:
# Define local repo - this is the same location as i have set up for the Archiva 'dev' repo.
<localRepository>/opt/maven-repo/dev</localRepository>
# Define the Archiva mirror i set up
<mirror>
<id>mirror</id>
<url>http://localhost:8080/repository/mirror/</url>
<mirrorOf>external:*</mirrorOf>
</mirror>
When I execute the build Maven grabs everything external via the mirror and then adds the built artifact to dev, along with the other jars it grabbed from mirror. So i now have some duplicate jars...
\repo\mirror\junit\junit
\repo\mirror\classworlds\classworlds
\repo\dev\junit\junit
\repo\dev\classworlds\classworlds
\repo\dev\me\myartifact
My question is, is the correct approach? Really I want to keep 'dev' with just my artifacts and mirror with everything from central - i don't want duplicates.
Should I be using the LocalRepository config in settings.xml or should I be using 'mvn deploy' to put the artifact in my Archiva repository by a different method?
Could someone clarify the different use cases for a local and remote repository?
Finally, how should I be defining my POM? Currently, I have just defined
<distributionManagement>
<repository>
<id>dev</id>
<url>file:///repo/dev</url>
</repository>
</distributionManagement>
Should i be adding in my mirror?
To put artifacts in your repository manager you should use the default which is maven-deploy-plugin which can be controlled by distributionManagement. The target where to put those things is controlled by defining the distributionManagement.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<distributionManagement>
<repository>
<id>releases</id>
<name>Release</name>
<url>http://urlArchiva/releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Snapshots</name>
<url>http://urlArchiva/snapshots/</url>
</snapshotRepository>
...
</distributionManagement>
...
</project>
The repositories which are used to consume artifacts from is defined in the settings.xml
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://serverUrlArchiva/public/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
On Bamboo you should be able to control which settings.xml is used to have an local repository per build which makes build independent from each other.

What does "http://central" mean in my Maven settings.xml?

I've been copying "sample" settings.xml files for ages now, and almost all of them seem to include a repository with the URL http://central. This bugs me, because of course there could actually be a machine on the local domain called "central", so this is a valid URN, but it also must (might?) have some special meaning to Maven.
Is it just shorthand that's commonly used, but the actual URL is ignored? Could I replace it with something else, or remove it entirely? Is it documented anywhere?
If it matters, I develop on a corporate network that has an internal iBiblio mirror, that acts as "central" for us.
AFAIK, it is a bogus URL which mentions at Configure Maven to Download from Nexus as the following example: -
<settings>
<mirrors>
<mirror>
<!--This sends everything else to /public -->
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<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>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<!--make the profile active all the time -->
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
The nexus profile is configured to download from the central repository with a bogus URL of http://central.
This URL is overridden by the mirror setting in the same settings.xml file to point to the URL of your single Nexus group. The nexus group is then listed as an active profile in the activeProfiles element.
I hope this may help.
We also used exactly this sample config, even with the same comments for about 15(!) years without any problems. For maven builds it does not matter, as always nexus is requested for any dependencies.
But today I tried to built a project with a combined ant+maven build which failed to get dependencies via artifact:remoteRepository Task from central Repo.
The solution was to fix the "url" tag in the central repo: https://repo.maven.apache.org/maven2
So it looks like it doesn't matter in most cases, but to avoid any corner cases, always use the right url.

Resources