How does maven know which repo to use for a dependency? - java

First off, I searched google but cant seem to find an answer for this. Apologies if its an obvious answer.
In maven we can define 0 or more repositories where it looks for resources. Repositories can be defined in settings.xml or within your pom. By default if you define no repositories everything will come from a repository name 'central' which is just the default one maintained by maven.
The below setup pom snippet comes from the jboss eap sample apps. When I do a mvn clean install I can see some things are pulled from central and some from the jboss repos. There does not seem to be anything in the dependency tag that tells maven which repository contains the dependency so how does it decide? Is it some how tied to group ID in the dependency or does maven just check all the repos one by one till it finds the first one that contains the jar?
<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.xml.bind</groupId>
<artifactId>jboss-jaxb-api_2.3_spec</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jboss-enterprise-maven-repository</id>
<url>https://maven.repository.redhat.com/qa/</url>
</repository>
<repository>
<id>jboss-enterprise-maven-repository-ea</id>
<url>https://maven.repository.redhat.com/earlyaccess/all/</url>
</repository>
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>

Maven just goes through the list and looks into all the repositories.
It is not possible to tie dependencies to special repositories.

Lets take a look at the official documentation:
Remote repository URLs are queried in the following
order for artifacts until one returns a valid result:
Effective settings:
Global settings.xml
User settings.xml
Local effective build POM:
Local pom.xml
Parent POMs, recursively
Super POM
Effective POMs from dependency path to the artifact.
For each of these
locations, the repositories within the profiles are queried first in
the order outlined at Introduction to build profiles.
Before downloading from a repository, mirrors configuration is
applied.
Effective settings and local build POM, with profile taken into
account, can easily be reviewed to see their repositories order with
mvn help:effective-settings and mvn help:effective-pom -Dverbose.

Related

How to upload or deploy multiple versions of an artifact to Sonatype Nexus?

I'm looking for a way to upload and store multiple versions of an artifact to the Sonatype Nexus maven-2 repository, so a team has access to previous versions of the artifact if a new version was released and uploaded.
I upload a java library to the hosted maven-2 release repository. Everything works well until I upload another version of the same library to the same repository.
After uploading the second version all files are present in the repository, but Maven cannot resolve not first nether second versions.
I tried both ways to upload artifacts - manually with the nexus UI and using the Maven deploy command. Results are the same.
I believe there is a way to store multiple versions in one repository.
Is there a special configuration for that case?
Please, help me to figure out how can I solve this issue.
As I mentioned, I have all settings that allow me to deploy and download one artifact from nexus.
In the library pom.xml I have:
<groupId>com.company.lib</groupId>
<artifactId>LibName</artifactId>
<version>1.0.7</version>
<name>LibName</name>
...
<distributionManagement>
<repository>
<id>testdeploy</id>
<url>https://nexus.company.com/repository/testdeploy/</url>
</repository>
</distributionManagement>
In the project where I want to download a library I have:
<dependencies>
<dependency>
<groupId>com.company.lib</groupId>
<artifactId>LibName</artifactId>
<version>1.0.7</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>testdeploy</id>
<url>https://nexus.company.com/repository/testdeploy/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
In settings.xml I have:
<servers>
<server>
<id>testdeploy</id>
<username>...</username>
<password>...</password>
</server>
<servers>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>https://nexus.company.com/repository/maven-public</url>
<name>Nexus M2</name>
</mirror>
<mirror>
<id>central_new</id>
<mirrorOf>central</mirrorOf>
<url>https://repo.maven.apache.org/maven2</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>release</id>
<repositories>
<repository>
<id>testdeploy</id>
<name>custom repo</name>
<url>https://nexus.company.com/repository/testdeploy/</url>
</repository>
</repositories>
</profile>
</profiles>
After uploading two versions of the library to nexus I have the following file structure:
com
company
lib
LibName
1.0.6
LibName-1.0.6.jar
LibName-1.0.6.jar.md5
LibName-1.0.6.jar.sha1
LibName-1.0.6.pom
LibName-1.0.6.pom.md5
LibName-1.0.6.pom.sha1
1.0.7
LibName-1.0.7.jar
LibName-1.0.7.jar.md5
LibName-1.0.7.jar.sha1
LibName-1.0.7.pom
LibName-1.0.7.pom.md5
LibName-1.0.7.pom.sha1
maven-metadata.xml
maven-metadata.xml.md5
maven-metadata.xml.sh1
When I try to download any of these versions via Maven I get an error
"Could not find artifact com.company.lib:LibName:1.0.6 in nexus (nexus.company.com/repository/maven-public)"
Solution:
In my case there were two problems:
The "testdeploy" repository was not added in maven-public group.
The "testdeploy" repo was made to test deployment artifact's versions from maven. I wanted to deploy another version of the library into the real repo after testing. The problem was that the real repo still had the library with the same artifact id and version. So there was a conflict between the real repo and test repo ("testdeploy") even after adding the "testdeploy" version into the "maven-public" group. To test deployment I had to change the librarie's artifact id.
Once these two issues were solved I didn't need to specify "testdeploy" repository in pom.xml. Defining the settings of the mirror (maven-public) and the server credentials in settings.xml were enough to make it work.
Maven identifies a unique artifact by a combination of 3 values: the groupId, the artifactID and the version. Appending -SNAPSHOT to a version has some additional special behaviour described here
The unique identifier for your artifact per your first pom snippet, would be
com.company.lib:LibName:1.0.7
If you want different addressable artifacts, change the version number. If people are still using the original 1.0.7 you should be producing 1.0.8 or some other incremented version.
Worth noting that projects that build in this often use SemVer and it's a convention that works in well understood ways so is probably a safe place to start.
EDIT TO ADD:
Based on comments, and re-review it looks like whatever is trying to pull 1.0.6 is not doing so from https://nexus.company.com/repository/testdeploy/. Instead it's trying to pull from nexus.company.com/repository/maven-public and failing.
For the project trtying to pull 1.0.6 what is the repository config? Your settings.xml only adds the testdeploy repo if the releases profile is active, so the testdeploy repo would need to be called out in the pom.
Your approach is correct and the normal way to work with different versions.
I guess you just have problems with different repository definitions in your Nexus, or some other network related issue.

Maven can not resolve dependencies from private nexus [duplicate]

I am trying to understand how maven downloads the binaries from the repositories.
For example, I have the following dependency for my project:
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.1</version>
</dependency>
Now, these binaries are present in http://mvnrepository.com/.
In pom.xml, we have <repositories> tag where we specify the repository URL from where maven can download the files, template:
<repositories>
<repository>
<id>mvnrepository_id</id>
<name>mvnrepository.com</name>
<url></url>
</repository>
Now, my doubt is, what should be the value of the <url>; does it need to be the base url , like http://mvnrepository.com/ or the complete URL --> http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs
To me it appears that is should be the base url else for each dependency we have to put the complete URL.
Can anyone help me understand this?
Unless you want to fetch artifacts from a repository different from the default Central Maven repository, you need not add the <repositories> section to your pom.xml. Read about Maven Repositories here and here.
And the url for default Central Maven repository is http://repo.maven.apache.org/maven2/.
PS: The URLs you have posted are the ones for the Website.

Maven add WorldEdit Dependencies

How can I add this WorldEdit dependency to my Maven project?
http://maven.sk89q.com/artifactory/repo/com/sk89q/worldedit/worldedit-bukkit/
I need the 6.1.1-SNAPSHOT.
Is there an algorithm to get
Group ID
Artifact ID
and Version?
It's important you understand the task at hand. Maven downloads dependencies from remote repositories based on their unique coordinates. There are two kind of repositories:
release repositories that host release versions of dependencies, i.e. final versions.
snapshot repositories that host snapshot versions of dependencies, i.e. versions that are currently in development, and are not stable yet.
A Maven coordinate is a set (groupId, artifactId, version). It uniquely identifies every dependency (truth be told, there are actually a packaging and a possibly a classifier but it's not important here).
Your problem is to declare a dependency to the worldedit-bukkit-6.1.1-SNAPSHOT dependency. Let's see:
the repository here is http://maven.sk89q.com/artifactory/repo: it is the root of the URL you linked to.
the groupId is com.sk89q.worldedit: this is the rest of the URL, right before
the artifactId, which is worldedit-bukkit and
the version, which is 6.1.1-SNAPSHOT.
If you breakdown the URL, you get
http://maven.sk89q.com/artifactory/repo/com/sk89q/worldedit/worldedit-bukkit/6.1.1-SNAPSHOT/
that is translated into the following Maven coordinates:
{REPOSITORY_URL}/{groupId where dots are slashes}/{artifactId}/{version}/
So now, we need to tell Maven about the repository. By default, Maven looks for artifacts in what's called Maven Central, so we need to add this repository. This is done either in the POM or in the settings.xml file, by adding the following configuration:
<repositories>
<repository>
<id>sk89q-snapshots</id>
<url>http://maven.sk89q.com/artifactory/repo</url>
<releases>
<enabled>true</enabled> <!-- releases enabled: this specific repository also hosts release versions -->
</releases>
<snapshots>
<enabled>true</enabled> <!-- snapshots enabled: we declare a SNAPSHOT repository because we need to download a SNAPSHOT dependency -->
</snapshots>
</repository>
</repositories>
Next step is to actually declare the dependency. This is done in the POM, with the following configuration:
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>6.1.1-SNAPSHOT</version>
</dependency>
And that's it!

JAHMM Package Maven

I need to work with be.ac.ulg.montefiore.run.jahmm package for Hidden Markov Models in java.
My project is a mevenized project so I need to use the corresponding dependency.
<dependency>
<groupId>be.ac.ulg.montefiore.run.jahmm</groupId>
<artifactId>jahmm</artifactId>
<version>0.6.2</version>
</dependency>
The above dependency is not being resolved in my project.
Does anyone know how to help me?
Thank you.
Your dependency is not in the Maven Central Repository.
Find out the repository used by the authors to publish their artifacts and add this repository to your POM or to your settings.xml.
If it is not published to the usual online maven repositories, you will need to install it on your local machine first.
So download the sources, go to the top level and do the usual
mvn install
Once you installed jahmm locally, your project can resolve it from your maven cache.
Adding this repository should do the trick:
<repositories>
<repository>
<id>jsi</id>
<url>http://repo.springsource.org/libs-release-remote</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>be.ac.ulg.montefiore.run.jahmm</groupId>
<artifactId>jahmm</artifactId>
<version>0.6.2</version>
</dependency>
...
</dependencies>

How can I add source code to my dependency libraries in Maven?

For instance, I have included into my dependencies junit-addons : junit-addons. But in the maven repository there isn't any source code. And I know it exists (I have downloaded it). How can I modify the dependencies in order to use libraries from my local project instead from the maven repository (I would omit the junit-addons from the respository and use a local JAR and its source code instead).
Note: I use m2eclipse.
I've solved the problem in a very straight forward way:
I have copied into the folder ${user.home}/.m2/repository/{group-name}/{artifactId}/{version}/ the source file following MAVEN standard: {artifactId}-{version}-sources.jar and it works as a charm! Eclipse checks the local repository and finds the sources.
I don't know if this is the MAVEN way, though.
How can I modify the dependencies in order to use libraries from my local project instead from the maven repository
You can't. If a sources JAR isn't available in the central repository, just put the sources somewhere on your file system in a folder, JAR or zip (you could install:install-file a sources archive in your local repository, following Maven's conventions) and setup Eclipse to use them (right-click on the JAR under Maven Dependencies in the Package Explorer, select Java Source Attachment and setup the Location path).
I use free version of Artifactory repository. I created a jar file {artifactId}-{version}-sources.jar and uploaded to the repository into the same group-id as binary jar file.
Then in my pom I added dependency:
<dependency>
<groupId>mygroupid</groupId>
<artifactId>artifact</artifactId>
<version>1.0</version>
<classifier>source</classifier>
</dependency>
During maven build phase source jar was downloaded to my local repository.
I use netbeans 7.0 and it automatically managed everything for me. For example, right click on method and choosing go toSource correctly brings me to source code in the jar.
You could use the install-file mojo to locally install artifacts into your local maven repository. If you want to share this artifact with others (say your team or another workstation), you could use your own repository manager (e.g. Nexus) and configure it as a mirror for any repository, e.g. central. Nexus will fetch (and cache) artifacts from central. Additionally, you may upload just about any artifact (like junit-addons sources) to your nexus installation.
In order to do configure a mirror, you'll have to edit ${user.home}/.m2/settings.xml
<settings>
<!-- SNIP -->
<mirrors>
<mirror>
<id>nexus-releases</id>
<mirrorOf>*</mirrorOf>
<!-- replace nexus.example.com with the location of your nexus installation -->
<url>http://nexus.example.com/releases</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
<id>nexus</id>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</pluginRepository>
</profile>
</profiles>
</settings>
After you have downloaded it into your local repository, you could make a copy of it. Give it a new artifactId (e.g. libraryName-myVersion) and add dependencies in the pom. Make sure you change the folder names, jar names, pom names and the artifactId itself in the pom. Store everything in your local repository. Now you can use your hacked version of your dependency.
But to be honest, I do not thing this is a good idea to do. But maybe it helps/could not be avoided in your case.

Categories