Maven - installing artifacts to a local repository in workspace

Viewed 48022

I'd like to have a way in which 'mvn install' puts files in a repository folder under my source (checkout) root, while using 3rd party dependencies from ~/.m2/repository.

So after 'mvn install', the layout is:

/work/project/
    repository
      com/example/foo-1.0.jar
      com/example/bar-1.0.jar
    foo
      src/main/java
    bar
      src/main/java

~/.m2/repository
    log4j/log4j/1.2/log4j-1.2.jar

(In particular, /work/project/repository does not contain log4j)

In essense, I'm looking for a way of creating a composite repository that references other repositories

My intention is to be able to have multiple checkouts of the same source and work on each without overwriting each other in the local repository with 'install'. Multiple checkouts can be because of working on different branches in cvs/svn but in my case it is due to cloning of the master branch in git (in git, each clone is like a branch). I don't like the alternatives which are to use a special version/classifier per checkout or to reinstall (rebuild) everything each time I switch.

5 Answers

Maven can search multiple repositories (local, remote, "fake" remote) to resolve dependencies but there is only ONE local repository where artifacts get installed during install. It would be a real nightmare to install artifacts into specific locations and to maintain this list without breaking anything, that would just not work, you don't want to do this.

But, TBH, I don't get the point. So, why do you want to do this? There might be alternative and much simpler solutions, like installing your artifacts in the local repository and then copying them under your project root. Why wouldn't this work? I'd really like to know the final intention though.

UPDATE: Having read the update of the initial question, the only solution I can think of (given that you don't want to use different versions/tags) would be to use two local repositories and to switch between them (very error prone though).

To do so, either use different user accounts (as the local repository is user specific by default).

Or update your ~/.m2/settings.xml each time you want to switch:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository>${user.home}/.m2/repository</localRepository>
  <!--localRepository>${user.home}/.m2/repository2</localRepository-->
  ...
</settings>

Or have another settings.xml and point on it using the --settings option:

mvn install --settings /path/to/alternate/settings.xml

Or specify the alternate location on the command line using the -Dmaven.repo.local option:

mvn -Dmaven.repo.local=/path/to/repo

These solutions are all error prone as I said and none of them is very satisfying. Even if you might have very good reasons to work on several branches in parallel, your use case (not rebuilding everything) is not very common. Here, using distinct user accounts migh be the less worse solution IMO.

This is not possible with the command line client but you can create more complex repository layouts with a Maven repository server like Nexus.

The reason why it's not possible is that Maven allows to nest projects and most of them will reference each other, so installing each artifact in a different repository would lead to lots of searches on your local hard disk (or to failed builds when you start a build in a sub-project).

I can see that you do not want to use special versions or classifiers but that is one of the best solutions to solve this problem. I work on the same project but different versions and each mvn install takes half an hour to build. The best option is to change the pom version appended with the change name, for example 1.0.0-SNAPSHOT-change1 that I'm working on thereby having multiple versions of the same project but with different code base.

It has made my life very easy in the long run. It helps run multiple builds at the same time without issues. Even during SCM push, we can skip the pom file from staging so there can always be 2 versions for you to work on.

In case you have a huge project with multiple sub-modules and want to change all the versions together, you can use the below command to do just that

mvn versions:set -DnewVersion=1.0.0-SNAPSHOT-change1 -DprocessAllModules

And once done, you can revert using

mvn versions:revert

I know this might be not what you are looking for, but it might help someone who wants to do this.

Related