copy artifact from local maven repository - maven

I don't understand why this is so difficult:
In a script, I need to copy an artifact from nexus to a certain directory. Using the Nexus REST API I would have to specify the repository which I don't want to have to know about. So I tried getting the artifact with maven-dependency-plugin's get goal instead, which works well. (In that case I get it from a group on our nexus which includes both, releases and snapshots.)
However, I now have the artifact in my local repo and the same plugin's "copy" goal does not seem to be able to get that artifact out of there. Is it really necessary to descend into the .m2 folder and grab that jar with the unix cp command? Anybody ever copied artifacts from their local repos to other dirs before?
Alternatively, if someone can tell me how to get an artifact via the Nexus API without specifying the repo, that would work, too.

Just tried this, and it worked for me:
mvn dependency:copy-dependencies -DincludeArtifactIds=jcharts -DincludeGroupIds=jcharts -DoutputDirectory=/tmp/
This copied the artifact jcharts:jcharts to /tmp/ It was in my local (and remote) repo when this was executed.

Seems like the problem was the _maven.repositories file in conjunction with the particular maven setup at my company.
We don't put the info about the local repo in our settings.xml. It's all in the parent pom that all our projects use. But if you want to do some pure mvn-CLI magic you don't have the parent-pom so you have to provide the URL to the local repo yourself. This is possible with the dependecy:get goal, which is why I was able to download my artifact from our Nexus into my local repo.
When using copy, however, you can't specify a URL. But why would I want to? I just downloaded that artifact into my local repo, right?
That's where the _maven.repositories file comes into play. Even with the -o switch, maven3 consults that file, which specifies the original repo that the artifact came from. (thanks to the guys in this thread for posting their findings!). If it can't reach the repo, it will claim that your file isn't there. (Btw., this is not helpful imho. It should say something about the original repo not being reachable and that the file therefore won't be copied.)
This was the reason why copy didn't work for me.
Simply renaming that file does the trick.
I will have to investigate a cleaner solution to this, though.
To make things even more complicated, I couldn't use dependency:copy or dependency:copy-dependecies. For some reasons they require a pom, which I don't have in my usecase. What does work is org.apache.maven.plugins:maven-dependency-plugin:2.8:copy which I believe is supposed to be the same thing, but that's another story.
Thanks for your answers!

If you are using Sonatype Nexus, you should consider disabling "Central" as outlined in their book.
Otherwise, per #Keith, dependency:copy-dependency will do what you are trying to do. dependency:get specially downloads from remote repositories, as stated in the documentation
You can also force Maven to not download from non-local repositories l by running it in offline mode: -o
Edit
You can also use Maven Wagon Plugin to copy the file from your local repository to an arbitrary directory. This shouldn't require a pom (but you may need to provide the full URL to the jar).

I needed to be able to specify the group ID, artifact ID and version (and packaging), this worked for me:
mvn dependency:copy \
-Dartifact=org.openmrs.web:openmrs-webapp:2.2.0-SNAPSHOT:war \
-DoutputDirectory=/tmp

Related

Maven - dependency list and download artifacts

Is it possible to find all dependencies in a maven projects like mvn dependency:tree, save results to file and then use mvn command for download all dependencies from list file in command line?
thanks
In my experience the various plugins do not get a 100% coverage so the builds will fail. What worked for me, was to start with an empty .m2/repositories folder, and then do the maven commands you need to do, and then persist the now populated .m2/repositories folder.
I experimented with converting it to a local file repository in the project itself so we could do with offline builds, but this turned out to be too big for our purposes. It might not be that much of an obstacle today.
Unless you have very strict political requirements, the usual pragmatic solution is to have a local repository on your network like nexus or artifactory mirroring maven central which is then accessed as a mirror.

Maven and dependencies NOT in repository

We have a dependency third-party library that is available online in jar form, but it is not in Maven Repository, or known to be in any other repository.
How can we use pom.xml to auto-retrieve this dependency, based on a URL?
We don't want to store it in our Git repo, because that's A Bad Thing.
The idea here is that when people check out the project, they can use their IDE Maven integration (or just mvn command line tools) to download all the dependencies. So we would want to be able to also download this other third party dependency just like all the ones in Maven repo.
I have not been able to come up with an answer to this based on searches -- all solutions seem to be "download it first and create a local repo." Obviously Maven can download from the Internet, since that's how it connects to Maven Central and other repos. So I don't see why it cannot download arbitrary URLs that present packages in recognizable formats.
Long term, the best solution is to use your own artifact repository like Nexus, Artifactory or Archiva.
All of these have a manual upload function that you can use to set the groupId, artifactId and version, so you can then refer to the artifact as usual.
If you want to go really low tech, I think you can just put some machine's local repository behind an Apache, provided you grant read/write access.
Then you need to add your new repository in the Maven settings.xml file, as described here.
Maven uses the coordinates to navigate the repository (which has a specific layout) and verify artifact checksums for corruption/tampering using metadata files in specific locations of the repo.
AFAIK this is similar to other package management systems like APT and RubyGems that use repo manifests and don't allow arbitrary URL downloads.
Skipping the repository manager
If you really don't want or can't use a repository manager, you can always download the artifact and manually install it using the Maven Install Plugin:
mvn install:install-file -Dfile=your-artifact-1.0.jar -DgroupId=org.some.group -DartifactId=your-artifact -Dversion=1.0
However, you'll have to do this on every machine that runs the build, every time that artifact needs to change.

Export Maven dependencies and maintain repository folder structure

I'm trying to know whether it's possible to export/copy dependencies of a project managed using Maven while maintaining the folder structure that is adopted in the local repository.
The root of my need is that I have amassed through almost ten years a lot of artifacts in my local repository (~8GB). I am no longer working on those old projects from previous assignments that drew most of the artifacts in and now, I need to move just what is needed for one single project (~650MB of artifacts) to a different computer. I can't just set the other computer to download artifacts again because many of these artifacts were retrieved from a local Nexus proxy in previous assignments. Moreover, I don't have the source code for these artifacts so I can't just install them.
dependency:copy-dependencies doesn't do the trick because all artifacts are simply dumped in a single folder, instead of having say .m2\repository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar
I believe my question can also be rephrased as “How can I extract from my local Maven repository a subset of the repository that is related to only one specific project?”
You can actually use the Maven Dependency Plugin and its copy-dependencies goal, as you mentioned.
What you actually missed is its useRepositoryLayout option
Place each artifact in the same directory layout as a default repository.
example: /outputDirectory/junit/junit/3.8.1/junit-3.8.1.jar.
Type: boolean.
Since: 2.0-alpha-2.
Required: No.
User Property: mdep.useRepositoryLayout.
Default: false.
You could hence execute - as an example - the following:
mvn dependency:copy-dependencies -Dmdep.useRepositoryLayout=true \
-DoutputDirectory=.m2/repository
If you missing some dependency, then download that dependencies from other source and paste it in your .m2(maven local repository ) folder.

maven can't find my local artifacts

I can't seem to run mvn -o package because it complains with
The repository system is off line but the artifact
com.liferay.portal:util-bridges:jar:6.1.20 is not available in the
local repository.
But I checked my local repository and that artifact does exist there. I also tried the solution of setting updatePolicy to never in the settings.xml file but that failed to work.
Prior to Maven 3.0.x, Maven did not track the origin of files in the local repository.
This could result in build issues, especially if you were building something that listed the (now dead) very borked java.net2 repository... Not only did that repository change released artifacts (extremely bad and evil practice) but it also published artifacts at the same coordinates as artifacts on central but with different content (unbelievably evil)
So you could have the build work (because you had commons-io:commons-io:2.0 from central) wipe your local repo and the build fails (because you now get commons-io:commons-io:2.0 from java.net2 which was a completely different artifact with different dependencies in the pom) or vice versa.
The above situation is one of the drivers for using a maven repository manager, because that allows you to control the subset of a repository that you expose downstream and the order in which artifacts are resolved from multiple repositories (usually referred to as routing rules)
In any case, when maven switched to Aether as the repository access layer, the decision was made to start tracking where artifacts come from.
So with Maven 3.0.x, when an artifact is downloaded from a repository, maven leaves a _maven.repositories file to record where the file was resolved from. If you are building a project and the effective list of repositories does not include the location that the artifact was resolved from, then Maven decides that it is as if the artifact was not in the cache, and will seek to re-resolve the artifact...
There are a number of bugs in 3.0.x though... The most critical being how offline is handled... Namely: when offline, maven 3.0.x thinks there are no repositories, so will always find a mismatch against the _maven.repositories file!!!
The workaround for Maven 3.0.x is to delete these files from your local cache, eg
$ find ~/.m2/repository -name _maven.repositories -exec rm -v {} \;
The side effect is that you loose the protections that Maven 3.0.x is trying to provide.
The good news is that Maven 3.1 will have the required fix (if we can ever get our act together and get a release out the door)
With Maven 3.1 when in offline mode the _maven.repositories file is (semi-)ignored, and there is also an option to ignore that file for online builds (referred to as legacy mode)
At this point in time (June 1st 2013) the 4th attempt to cut a release that meets the legal and testing requirements is in progress... So, assuming that the 4th time is lucky, I would hope to see 3.1.0-alpha-1 released in 3-4 days time... But it could be longer given that we want to give the changes in 3.1 enough time to soak to ensure uses builds don't break (there was a change in an API exposed (by accident-ish - the API is needed by the site and dependency plugin) that plugin authors have depended on (even though they shouldn't have) so there is potential, though we think we have all the bases covered)
Hope that answers your question (and maybe a few more you didn't know you had ;-) )
I also had to remove _remote.repositories in the same way as the _maven.repositories described above. I'm using Maven 3.1.1
find ~/.m2/repository -name _remote.repositories -exec rm -v {} \;
I had this issue when i was using apache-maven-3.0.4, the issue is gone right after i move to apache-maven-3.3.1.
I had this issue in Ubuntu Linux when I've installed local artifacts via a shell script. The solution was to delete the local artifacts and install them again "manually" - calling mvn install:install-file via terminal.

How to update maven repository manually from the maven build?

We do not have our own repository at the moment. So, when we build with maven it creates .m2 repository in the home directory of the current user.
Now there are two third party jars which are not found in the Maven Central. Suppose one of them is hasp-srm-api.jar. Today the process is this:
a. The pom.xml of the project depending on hasp-srm-api.jar contain these lines:
<dependency>
<groupId>com.safenet</groupId>
<artifactId>hasp</artifactId>
<version>1</version>
</dependency>
b. Before doing the first build we execute the following command:
mvn install:install-file -Dfile=hasp-srm-api.jar -DgroupId=com.safenet -DartifactId=hasp -Dversion=1 -Dpackaging=jar
My question is this - is it possible to automate this step? I would like to be able to tell maven to check whether the hasp artifact exists and if not - install it manually using the aforementioned command line. How can I do it?
NO. It is not possible to have maven automatically deploy an artifact into a repository in the fashion you suggest. This goes for both local and remote repositories. If the artifact exists in a some repository somewhere, you can add that repository to your build's list of known remote repos, but other than that you have to add it yourself.
You can add it to your local .m2 repository, but that will then only be good for that individual environment. Other dev's will have to repeat the process. This is one of the main attractions of running your own repository server( like Nexus ); you can add the artifact to that repository and then everyone in your organization can use it forever. There is still no way to automate the deployment of the artifact, but it's easy to do and is permanent.
Note, setting up a repository manager is very easy to do. It's highly recommended. It makes the whole Maven thing make a whole lot more sense.
The best solution for such problems is using a repository manager which results in installing such kind of dependencies only once into the repository manager and the whole company can use it a usual dependency. That's it.
Other option you have is to write your own maven plugin. May be below link will be right place for you start
MOJO FAQ

Resources