26

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.

Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
IttayD
  • 28,271
  • 28
  • 124
  • 178
  • I think that what you're looking for is the dependency:copy-dependencies goal See: http://maven.apache.org/plugins/maven-dependency-plugin/copy-dependencies-mojo.html This is often performed as a prelude to building an installable package, or if you want to invoke a third-party tool that will build a classpath from all jars in a specified directory. – Kevin Wright Jan 08 '10 at 16:02

5 Answers5

33

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.

jotik
  • 17,044
  • 13
  • 58
  • 123
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • i didn't ask how i can install to multiple repositories and my example shows the files are installed in one repository (/work/project/repository). how do i tell maven to search for multiple repositories on local disk? i know of the "fake" remote repository technique, but this causes maven to copy the files from the fake remote to the local repository. – IttayD Jan 07 '10 at 14:15
  • Well, this may not be what you asked for but this is what you are trying to do and, in your example, there are indeed 2 local repositories: `/work/project/repository` and `~/.m2/repository`. But this is not possible, there is only ONE local repository (wherever it's located). Please clarify what you are trying to achieve and your needs. As I said, I don't get the whole thing. – Pascal Thivent Jan 07 '10 at 14:21
  • thanks for the effort. in both cases, the local repository will also be populated with all 3rd party artifacts, wasting disk space. marking as a solution since it probably doesn't get any better – IttayD Jan 10 '10 at 05:16
  • 6
    I disagree Pascal, there are many situations where that could be (and is) useful. The first that comes to mind is for CI builds, and indeed Jenkins offers the option to have local repositories using the global local repo, a repo local to the jenkins executor node, or a repo local to the workspace. This is very useful to avoid conflicting builds, especially when you run them concurrently. – haylem Oct 25 '12 at 13:43
  • 3
    And similarly, on my workstation I often work on several bugs at once and require to run multiple builds at once because of lengthy build times or just because if one needs to be left in a state of disarray while waiting for a solution or decision of a higher-power, I want to be able to stash it away (yes, if we used git we could do that, but unfortunately we use svn :) ), and work on something else seamlessly. Of course, I could use a VM for that, or different accounts, but that's a rather bad overhead. – haylem Oct 25 '12 at 13:44
  • So, a complement and maybe easier solution for the OP, on top of your last 2 suggestions, is to drop a settings.xml in your top-level maven module for this workspace. It will get picked up by the maven build. The priority is 1) cli-given repo 2) workspace repo 3) global repo. – haylem Oct 25 '12 at 13:45
  • Actually that doesn't seem to work, so scratch my last comment. The workspace-local settings.xml doesn't seem to be able to do everything the global one does, or at least I can't get it to set up a localRepository that works... – haylem Oct 25 '12 at 15:13
  • a common use case for multiple local repos is when some dependencies can only be copied to customer computers if obfuscated, which eliminates the ability to effectively debug code. So un-obfuscated dependencies and source javadoc are stored on an external encrypted drive. This works as long as the IDE & maven are configured to not copy the dependencies into the workspace / onto the workstation. – JasonRobinson Jan 24 '17 at 19:17
1

This is INDEED possible with the command line, and in fact is quite useful. For example, if you want to create an additional repo under your Eclipse project, you just do:

mvn install:install-file -DlocalRepositoryPath=repo \
   -DcreateChecksum=true -Dpackaging=jar \
   -Dfile=%2 -DgroupId=%3 -DartifactId=%4 -Dversion=%5

It's the "localRepositoryPath" parameter that will direct your install to any local repo you want.

I have this in a batch file that I run from my project root, and it installs the file into a "repo" directory within my project (hence the % parameters). So why would you want to do this? Well, let's you say you are professional services consultant, and you regularly go into customer locations where you are forced to use their security hardened laptops. You copy your self-contained project to their laptop from a USB stick, and presto, you can do your maven build no problem.

Generally, if you are using YOUR laptop, then it makes sense to have a single local repo that has everything in it. But to you who got cocky and said things like "why would you want to do that", I have some news...the world is a bigger place with more options than you might realize. If you are using laptops that are NOT yours, and you need to build your project on that laptop, get the resulting artifact, and then remove your project directory (and the local repo you just used), this is the way to go.

As to why you would want to have 2 local repos, the default .m2/repository is where the companies standard stuff goes, and the local "in project" repo is where YOUR stuff goes.

jotik
  • 17,044
  • 13
  • 58
  • 123
Ken Kopelson
  • 157
  • 1
  • 4
0

FYI: symlinks work in Windows7 and above so this kind of thing is easy to achieve if all your code goes in the same place in the local repo, i.e /com/myco/.

type mklink for details

teknopaul
  • 6,505
  • 2
  • 30
  • 24
0

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

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 1
    You're describing how to create a remote composite repository. I'm looking for something similar, but for a local repository. (search in different folders, install into one) – IttayD Jan 07 '10 at 14:16
  • Install Nexus on your local computer to get this behavior. But as I said: It's not possible to achieve with Maven alone. – Aaron Digulla Jan 07 '10 at 14:48
  • even with nexus, i will still need a local repository where maven will download all 3rd party artifacts. – IttayD Jan 07 '10 at 19:41
  • There is no way to keep the local repository clean. – Aaron Digulla Jan 08 '10 at 08:11
  • btw, about the reason, i don't see why this is a problem. i simply want to be able to specify 2 local repositories that are searched where one is designated as the 'install-to' repository and the other as the 'download-to' repository. if i have several projects where each has a different 'install-to' repository, then this is a configuration problem i need to fix. – IttayD Jan 08 '10 at 19:03
  • @IttayD: It's not possible because the settings file allows only a single path. If you need more, you must download the source for Maven, find the plugin(s) which read this property and patch them to accept a list instead. – Aaron Digulla Jan 10 '10 at 14:01
0

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.

v1shnu
  • 2,211
  • 8
  • 39
  • 68