Set the maven local repository location in a pom.xml file? - java

It's possible to set the maven local repository in settings.xml:
<localRepository>${user.home}/.m2/repository</localRepository>
And it's possible to set the maven local repository on the command line:
mvn clean install -Dmaven.repo.local=repository
Is it possible to specify within the pom.xml itself?
Note: I'd like a way to specify, in the pom.xml, where maven initially searches for artifacts (by default, ~/.m2/repository) and where maven installs artifacts via mvn install (by default, ~/.m2/repository).

According to the Maven POM Reference and the Guide to using multiple repositories, you can specify repositories in pom.xml too.
There are two different ways that you can specify the use of multiple repositories. The first way is to specify in a POM which repositories you want to use
And according to Introduction to repositories, you can use the file:// protocol in <url>.
Remote repositories refer to any other type of repository, accessed by a variety of protocols such as file:// and http://.
So the following works:
<project>
...
<repositories>
<repository>
<id>example-repo</id>
<name>Example Repository</name>
<url>file://path/to/your/local/repository</url>
</repository>
</repositories>
</project>
Edit:
Based on your comment and edit, you need to override the default repository and Maven home directory in pom.xml.
I've found a topic about disabling central repository, and tried out the answers, but Maven still uses the values from settings.xml. This answer in another thread explains why:
settings.xml allows you to override definitions in pom.xml, not the other way round.
So it's seems it is not possible to override the default mechanism from pom.xml, Maven will search for dependencies in repositories configured in settings.xml and will install to Maven home specified in that file.

If the problem is having to write the options every time when running maven, you can use a feature available since version 3.3.1 that allows you to set command line options in your project (or parent project of your module). Read #Brice's answer: https://stackoverflow.com/a/48583079
So with this feature in mind, you can achieve a similar result by setting up a new settings.xml with the <localRepository> pointing to the location you desire and use maven.config in your project to make maven use the new settings.xml, which by the way can be anywhere you want.

Related

Replace maven library with local one

I have a dependency in pom on some library.
I want to make some changes in it, test it locally and if it will work fine - deploy it to remote repo.
So I have locally made some changes in this library, installed it as a jar, and want to replace in my main project remote library with the local one.
What is proper way to do it?
You can override default maven repository in project's pom:
<repositories>
<repository>
<id>central</id>
<url>file://d:/repo</url>
</repository>
</repositories>
When resolving dependencies, Maven looks in your local repository ($HOME/.m2/repository). So if you have installed your modified dependency into your local repository (e.g. through mvn install) then when you build your main project, it will be used.
To make this more obvious, you may want to change the versions being used in both the library and your main project POM, so that you can be sure your version is being used for testing.
You may also find this question/answer useful: How do I force Maven to use my local repository rather than going out to remote repos to retrieve artifacts?
Maven first looks in your local repository in
C:\Users\User\.m2\repository
and if it can't find the library, then it looks in remote repos. If I understand your question correctly, this should be happening automatically as long as you point the correct version in the POM.

Maven dependency issue - artifact not found in central repo

I'm trying to build the project from this site http://www.joptimizer.com/usage.html. I downloaded the sources jar file, unpacked it and ran maven package in the root folder. Maven fails at the last minute saying it couldn't resolve the dependency..
could not find artifact seventytwomiles:architecture-rules:jar:3.0.0-M1 in central repo - repo.maven.apache.org/maven2 ..
I have a feeling I might need to change something in the pom.xml file for this to work, but have no idea what. Googling for this missing dependency lead me no where. In general, how would one know what to do to handle such errors (and also please help with this specific case).
Specifically
According to the Building notes on http://www.joptimizer.com/usage.html:
JOptimizer is build on maven 3.0. Before building it, you must resolve
(in pom.xml) the external dependency on Colt and other dependencies
that aren't in public repositories. Please refer to the "Dependencies"
report for a complete treatment. For ease of use a boundle with
these external libraries is provided (visit "Download"): extract the
boundle in a folder and run the "maven-install.cmd" (translate it in
your own shell language), and you will get the artifacts in your local
repository.
To get the bundle for this, go to http://sourceforge.net/projects/cvxopt/files/, and download the appropriate version of joptimizer-3.X.X-dependencies.zip. Unzip in your own folder, and run mvn install:install-file -DgroupId=seventytwomiles -DartifactId=architecture-rules -Dversion=3.0.0-M1 -Dpackaging=jar -Dfile=architecture-rules-3.0.0-M1.jar -DpomFile=architecture-rules-3.0.0-M1.pom
Generally
Use a tool like http://mavenrepository.com to search for another version of the missing dependency and update your POM with the proper version. If MVNRepository doesn't know about it, you can install the dependency yourself. If you are working with a group of developers, as Eric Jablow mentions, an artifact repository like Nexus or Artifactory is great for sharing non-public dependencies. If it's just you, you can install the artifact in your local repo as described here: How to manually install an artifact in Maven 2?
You should add your own repository manager like Nexus or Artifactory. Then, find out where this dependency is kept; there are repositories other than central. If it's kept on another repository, have your repository mirror that too.
Otherwise, Nexus or Artifactory have commands to enter the dependency manually. Create a local repository called "Third-party" and add it there.
Finally, change your settings.xml file to refer everything to your repository manager.
The most common case for this is when a company refuses to license their products to be held at the central repository. For example, Microsoft won't let its sqljdbc.jar file be distributed through Central. So, you need to add it by hand.
Change the dependency as follows
<dependency>
<groupId>org.architecturerules</groupId>
<artifactId>architecture-rules</artifactId>
<version>3.0.0-rc1</version>
<scope>test</scope>
</dependency>
Add the repository in pom
<repositories>
<repository>
<id>architecturerules.googlecode.com</id>
<url>http://architecturerules.googlecode.com/svn/maven2/</url>
</repository>
</repositories>

How does Maven interact with different repositories?

How does Maven interacts with different repositories like Nexus and Artifactory?
Is it done using their REST APIs? It is possible to resolve dependent artifacts to actual locations to get them from using these APIs, but the two APIs are somewhat different form each other (as far as i see [Artifactory] [Nexus]) and the repository definition element in Maven pom files does not contain a property to state the type of the repository.
So how does Maven resolves artifact's groupId, artifactId and version to an actual file in different repositories? Does these repositories implement some other standardized API that enables Maven to request files from them in an repository-agnostic way?
Yoy define repositories to search artifacts in 2 ways:
1) in your pom.xml in project section
<project>
....
<repositories>
<repository>
...
<url>...</url>
</repository>
</repositories>
</project>
2) and/or in file $USER_HOME$/.m2/settings.xml (there are plenty examples on WEB)
Maven downloads artifacts from by constructing URL of artifact using repository URL and appending path according to artifact group, id, version, type and classifier. And converts dots in groupId into '/'
RepoUrl/groupId/artifactId/version/artifactId-version-classifier.type
Examples:
https://repository.apache.org/content/repositories/releases/commons-io/commons-io/2.4/commons-io-2.4.jar
https://repository.apache.org/content/repositories/releases/commons-io/commons-io/2.4/commons-io-2.4-sources.jar
https://repository.apache.org/content/repositories/releases/commons-io/commons-io/2.4/commons-io-2.4-javadoc.jar
This is convention and it's independent from Artifactory or Nexus. This is Maven. Everything is transfered through the HTTP or HTTPS. Additionally Maven handles MD5 and SHA1 files for security purposes.
Once downloaded, artifact stored in local repository on your workstation at $USER_HOME$/.m2/repositories (it have a structure similar to remote repository) that acts as a cache and proxy.
Typically Artifactory or Nexus are kind of local cache and proxy at company level with some functionality to manage it. Surely they host maven artifacts published by company developers.
Looks like a 3 levels of repositories: local - local company - global
Maven uses some kind of naming convention. In pom.xml you define a root URL of repository (e.g. http://download.java.net/maven/2/) and then maven is able to resolve an artifact by constructing a URL:
<root URL>/${group id where dots are replaced by slashes}/${artifact id}/${version}
So for the following dependency
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>2.0.0</version>
Maven will try to find poms and jar at http://download.java.net/maven/2/org/apache/lucene/lucene-core/2.0.0
That means every URI which follows this convention may serve as Maven repo.
maven uses normal http calls to interact with repositories. you don't need anything but an http server to serve a maven repository. maven relies on a specific directory hierarchy and a few metadata files. (the local on disk repository where maven caches files it has downloaded is the exact same format).

Include a Maven dependency only if it exists

I have a problem, I have a project which is based in a system that includes modules. This modules are other maven projects and are referenced from system POM. My problem is I'm sharing the system project with a workmate and we've got different modules.
So, is there a way to tell Maven that I want to include a module referenced in my POM only if this module exists? I mean, without compilation failure.
Thanks!
I would suggest to use profiles and activate them on file/exists option.
Use dependencyManagementis to pull all the dependency information into a common POM file, simplifying the references in the child POM file.
There are several solutions, depending on what you can do/want to achieve.
One approach is to install a Maven repository server at your company (in your local LAN or in a LAN that you and your colleague share). Build the system and then deploy the modules to the server.
In your build, you can add this new server like this (documentation):
<project>
...
<repositories>
<repository>
<id>my-internal-site</id>
<url>http://myserver/repo</url>
</repository>
</repositories>
...
</project>
Or you can both copy the base system and build it locally with mvn install. That will copy all artifacts into your local cache.
From there, you can reference them as usual. You don't need to include all the modules; just the ones you really need. That way, you and your friend don't have to use the same dependencies.

How to add missing maven libraries to Jetty

I am trying to launch a maven project, that I always launched manually in Tomcat, in Jetty. For this I am using the maven-jetty-plugin.
When executing jetty:run It seems like everything goes fine, except for the fact that Jetty does not find the dependencies defined in the POM.
If I run jetty:war, the war is built properly, using the dependencies, so that works. Why is jetty:run not including my libraries in WEB-INF/lib (or anywhere else)?
If you need a dependency for Jetty which resides somewhere other than the main Maven repo, add the following:
<pluginRepositories>
<pluginRepository>
<id>repo-id</id>
<url>http://my_other_repo.edu</url>
</pluginRepository>
</pluginRepositories>
I don't believe Jetty will use the existing repositories in your POM.
It really depends on the dependencies you have defined. For example, if you have defined a JNDI resource in your jetty.xml file, you will need the jetty-plus dependency. However, you will need this dependency for the execution of the plugin only. Plugins can have <dependencies/> and that is where you need to define it.
If you have a list of Jetty-specific classes that the plugin can't find, the best way to look up the dependencies is to use a site like www.jarvana.com.
By 'dependencies', do you mean other projects?
If so, you will need to install (mvn:install) these into the local repository before jetty:run will see them.
It's possible that jetty:war is packaging them and placing them into the lib folder without installing into the local repo.
For me I had one .jar file in my repo that was not getting picked up by Eclipse. I didn't figure out how to fix it in Eclipse, so my work around was to ...
Add a duplicate of the .jar file to the repo under a different groupId (different path under ~/.m2) using this command:
mvn install:install-file -Dfile=dhcp4java-1.0.0.jar -DgroupId=a_abc.hack -DartifactId=dhcp4java -Dversion=1.0.0 -Dpackaging=jar
Reference the new groupId , which requires only to update this entry for the dependency in pom.xml :
<groupId>a_abc.hack </groupId>

Categories