714

Maven 2 is driving me crazy during the experimentation / quick and dirty mock-up phase of development.

I have a pom.xml file that defines the dependencies for the web-app framework I want to use, and I can quickly generate starter projects from that file. However, sometimes I want to link to a 3rd party library that doesn't already have a pom.xml file defined, so rather than create the pom.xml file for the 3rd party lib by hand and install it, and add the dependency to my pom.xml, I would just like to tell Maven: "In addition to my defined dependencies, include any jars that are in /lib too."

It seems like this ought to be simple, but if it is, I am missing something.

Any pointers on how to do this are greatly appreciated. Short of that, if there is a simple way to point maven to a /lib directory and easily create a pom.xml with all the enclosed jars mapped to a single dependency which I could then name / install and link to in one fell swoop would also suffice.

Lii
  • 9,906
  • 6
  • 53
  • 73
  • If you're using Netbeans just follow these steps : [How do I install modules into the maven repository using Netbeans embedded Maven?][1] [1]: http://stackoverflow.com/a/339874/530153 – Rajat Gupta Dec 16 '12 at 05:10
  • 1
    I want to point out that this link http://stackoverflow.com/a/339874/530153 appears to work for installing the jars one at a time. – Paul Feb 12 '14 at 15:55

24 Answers24

616

Problems of popular approaches

Most of the answers you'll find around the internet will suggest you to either install the dependency to your local repository or specify a "system" scope in the pom and distribute the dependency with the source of your project. But both of these solutions are actually flawed.

Why you shouldn't apply the "Install to Local Repo" approach

When you install a dependency to your local repository it remains there. Your distribution artifact will do fine as long as it has access to this repository. The problem is in most cases this repository will reside on your local machine, so there'll be no way to resolve this dependency on any other machine. Clearly making your artifact depend on a specific machine is not a way to handle things. Otherwise this dependency will have to be locally installed on every machine working with that project which is not any better.

Why you shouldn't apply the "System Scope" approach

The jars you depend on with the "System Scope" approach neither get installed to any repository or attached to your target packages. That's why your distribution package won't have a way to resolve that dependency when used. That I believe was the reason why the use of system scope even got deprecated. Anyway you don't want to rely on a deprecated feature.

The static in-project repository solution

After putting this in your pom:

<repository>
    <id>repo</id>
    <releases>
        <enabled>true</enabled>
        <checksumPolicy>ignore</checksumPolicy>
    </releases>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
    <url>file://${project.basedir}/repo</url>
</repository>

for each artifact with a group id of form x.y.z Maven will include the following location inside your project dir in its search for artifacts:

repo/
| - x/
|   | - y/
|   |   | - z/
|   |   |   | - ${artifactId}/
|   |   |   |   | - ${version}/
|   |   |   |   |   | - ${artifactId}-${version}.jar

To elaborate more on this you can read this blog post.

Use Maven to install to project repo

Instead of creating this structure by hand I recommend to use a Maven plugin to install your jars as artifacts. So, to install an artifact to an in-project repository under repo folder execute:

mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...]

If you'll choose this approach you'll be able to simplify the repository declaration in pom to:

<repository>
    <id>repo</id>
    <url>file://${project.basedir}/repo</url>
</repository>

A helper script

Since executing installation command for each lib is kinda annoying and definitely error prone, I've created a utility script which automatically installs all the jars from a lib folder to a project repository, while automatically resolving all metadata (groupId, artifactId and etc.) from names of files. The script also prints out the dependencies xml for you to copy-paste in your pom.

Include the dependencies in your target package

When you'll have your in-project repository created you'll have solved a problem of distributing the dependencies of the project with its source, but since then your project's target artifact will depend on non-published jars, so when you'll install it to a repository it will have unresolvable dependencies.

To beat this problem I suggest to include these dependencies in your target package. This you can do with either the Assembly Plugin or better with the OneJar Plugin. The official documentaion on OneJar is easy to grasp.

Spooky
  • 2,848
  • 8
  • 24
  • 39
Nikita Volkov
  • 41,289
  • 10
  • 85
  • 162
  • 4
    I always assumed you could create a repository in the project, finally confirmed it, great! – albfan Feb 19 '12 at 10:40
  • This option can be coupled with a "provided" scope in the dependency to build against a library .jar that will be made available inside the container. We've done this to link to JNI libraries that are deployed inside of Tomcat's own /lib/ folder. – jricher Jun 20 '12 at 16:02
  • 19
    Two things to note: 1) I recommend using "${project.baseUri}repo" instead of "file://${project.basedir}/repo" to get an RFC-compliant url also on Windows. 2) If you structure your project into submodules, this approach seems to fail because ${project.baseUri} gets resolved to the module's subdirectory. Any idea how to resolve this problem? – Oliver Hanappi Jan 17 '13 at 07:37
  • Good, "Install to Local Repo" need everyone do 'local install', while this option only need one guy to do install and the others can share the installed. – leef Jan 19 '13 at 09:20
  • 8
    This nearly got me there - but Nikita's script tried to be too clever with the badly named JAR files I had. So I made a simplified version that does not do any guessing for the groupId: https://github.com/carchrae/install-to-project-repo – Tom Carchrae Feb 08 '13 at 00:05
  • 3
    such a brilliant answer!! There are 2 ways of doing something, the right way and the way that works, you sir does it the right way! – Panthro May 17 '13 at 15:44
  • 1
    here you also find info how to automatically generate the artifact from your jar file: https://devcenter.heroku.com/articles/local-maven-dependencies – Dirk Oct 24 '13 at 09:04
  • Is there a way to do this from `classes/` instead of from `my.jar`? The project I want to turn into an `in-project respository` is very difficult to build as a single jar. E.g., something like `mvn install:install-file -DlocalRepositoryPath=repo -Dfile=target/classes/... [...]`? – Alex Averbuch Nov 05 '13 at 08:50
  • @AlexAverbuch I don't know. Start a separate question. – Nikita Volkov Nov 05 '13 at 12:44
  • Thank you for taking the time to explain this. There's at least one other person who's just happy to go around adding "Don't do that you idiot!" comments on questions about this. – duma Jul 15 '14 at 04:07
  • Static in project repository performs very poorly for projects with many dependencies. The first time you build it will check this local directory even for jars that should be found in central. Subsequent builds are fine. – Pyrolistical Aug 27 '14 at 22:22
  • This works fine, but if I set `ignore` and delete the hash files the local repo and returns error 409 when trying to resolve. Anyone got a solution for this? – sydd Aug 28 '14 at 12:19
  • I would propose to use deploy:deploy-file along with -Durl=project::default::file:///path/to/repo for installing jars in this repository to create a proper repository structure. The local repository is not a full repository. – languitar Sep 03 '14 at 15:34
  • 1
    i wanted to try this approach so bad i went for it, though the jar files (slightly different versions) were already present in our Nexus. Love it. Thanks for a great and complete answer. – Peter Perháč Nov 26 '14 at 16:10
  • I tried this solution but I got an error: maven complains that I have no pom for my jar. Any clues? I use maven 3.2.1 – Giorgio Jan 27 '15 at 20:07
  • In-project local repo seems reasonable and is continuous-* compatible - but Maven makes everything to make it extremely difficult/impossible to use this idea transparently when you have submodules. There seems to be no property that always resolves to main module (typically parent) path. And then you have no way to point to the repo. Relatives path seem not to work. Enterprise pain at its best, delivered (again) by Maven and its lacking multi-module support. :-( – virgo47 Oct 13 '15 at 15:34
  • Remember this install:install-file approach works for multiple files, so you can do things like put the sources JAR in there too. – Gregory R. Sudderth Jul 27 '16 at 16:35
  • The local filesystem repo is a brilliant solution. Saved me a load of heartache – Lawrence Tierney Feb 03 '17 at 09:27
  • As of version 2.5 of the maven-install-plugin, if the target jar file was built by maven then the install-file action will be able to introspect the groupId, artifactId, and version. https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html – lmsurprenant Jun 16 '17 at 17:40
  • 1
    The static in-project repository solution is what I needed. Make sure to add the tags around it. I put mine above the tag and below the tag. – Kelly Bang Oct 10 '18 at 02:49
  • Hello Please I'm stuck here. After following all the steps, `mvn package` still doesn't resolve the files – Enoobong Apr 24 '19 at 11:56
  • I had to set the dependencies from the local file repo packages to optional `true`. Otherwise maven could not resolve the **transitive** dependencies in my consumer project (couldn't find artifact). Additionally I had to turn of "Resolve dependecies from Workspace projects" `resolveWorkspaceProjects=false` in my consumer project, because Eclipse couln't find the local repo from the open parent project then. – thomas.st Jan 12 '21 at 09:40
495

For throw away code only

set scope == system and just make up a groupId, artifactId, and version

<dependency>
    <groupId>org.swinglabs</groupId>
    <artifactId>swingx</artifactId>
    <version>0.9.2</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/swingx-0.9.3.jar</systemPath>
</dependency>

Note: system dependencies are not copied into resulted jar/war
(see How to include system dependencies in war built using maven)

Paul Verest
  • 51,779
  • 39
  • 174
  • 288
Pyrolistical
  • 26,088
  • 21
  • 78
  • 104
  • 4
    Thanks this is really close to what I want. Any way to add them all as a single entry? Say I have /lib with 10 jars, can I add them all somehow, for instance with /some/path/*.jar for the systemPath? or I still have to treat each as a known dependency? Still, really close to what I need, thanks! –  Dec 12 '08 at 21:47
  • 1
    I don't know of a way to do it by a group of jars, just do it this way, its more consistent – Pyrolistical Dec 12 '08 at 22:28
  • 11
    use a systemPath like this one: "${basedir}/lib/BrowserLauncher2-1_3.jar" ${basedir} is pointing to your project's root. – Frederic Morin Apr 19 '09 at 07:40
  • 2
    Scope system means that you must indicate to Maven2 where the library must be found (specified in systemPath), as the dependency will *not* be found in the local repository of Maven2. This can be usefull when the library is not present in any repository and you don't want to install it. However, the scope system is discouraged! – Romain Linsolas Sep 23 '09 at 08:15
  • 4
    It is better to use the project. prefix in your path like so: ${project.basedir}/lib/AwesomeLib.jar – Matthew McCullough Nov 25 '09 at 21:23
  • Please note that the groupId & artifactId need to be unique for this to work. – Matthew Farwell Apr 23 '10 at 20:34
  • 77
    While I understand that this is what the OP was asking for, I still want to underline that using a `system` scope is an horrible practice that is **strongly discouraged**. See [Dependency+Scopes](http://docs.codehaus.org/display/MAVENUSER/Dependency+Scopes). – Pascal Thivent Sep 18 '10 at 19:47
  • 1
    How to make that .jar will be packaged during `mvn package` ? – marioosh Aug 23 '11 at 13:08
  • The problem is the jar won't be packaged during mvn package for EAR or WAR files which is actually why I needed it. – Archimedes Trajano Oct 12 '11 at 23:50
  • 6
    @marioosh remember the original intent of the question was for quick experimentation. If you want to do a mvn package, install the jar into the repo. – Pyrolistical Oct 22 '11 at 05:55
  • Downvoted because I think Nikita's answer is much more comprehensive. The local repo approach is definitely better and really takes no extra effort to set up (even if you don't use her script) – BigMikeW Aug 27 '14 at 21:40
  • 3
    @BigMikeW Nikita is a male. This is common male name in Russia. – ᄂ ᄀ Dec 06 '14 at 12:56
  • @PascalThivent 2 reasons to avoid system scope: 1. It's a lot less convenient: Every good maven project should allow: `git clone project; mvn package` and build completely. 2. It breaks the transitive dependency model. For "throw away code" this may be ok; but if you write a_useful_project that you want to reuse in project2, when you put a dependency on 'a_useful_project' into project2/pom.xml, maven won't be able to also grab the system scope dependency. This is not an edge case: It's very common for a project to download at least 3x more transitive dependencies than are listed in the pom – Stan Kurdziel Apr 28 '15 at 22:41
  • @StanKurdziel What if you want to integrate a binary-only jar into your maven project which is *not* reachable from a maven repository? Then the only possibility to use the system scope and including the jar from `${project.build.path}/lib/...jar`. Instead of saying the ultimate truth, you should think a little bit more on some uncommon circumstances... – peterh Dec 17 '16 at 09:26
  • @PascalThivent My previous comment is also for you. – peterh Dec 17 '16 at 09:27
  • @Peterh why don't you want to install the binary-only jar to a maven repository? Having system scoped dependencies creates fundamentally broken maven projects. One of the greatest attributes about maven is that once you get the hang of one+ project build(s), you should be quite familiar with almost any other maven project build. If system scoped dependencies works for your case, more power to you; However in my opinion, this is not something to encourage for normal usage. – Stan Kurdziel Dec 17 '16 at 09:42
  • @StanKurdziel It is not a part of any maven repository. It is a binary-only thing, I have only a single jar file, without any maven repo. I have to produce a git tree, from which it is installable with a simple `mvn clean install`. The only meaningful solution is a system scope for that. Because you clearly show that you are perfectly incapable to understood others views, our talk here ends now. – peterh Dec 17 '16 at 10:36
  • @peterh See https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html for how to install a binary-only jar to your local maven repository. ex: `mvn install:install-file -Dfile=./jar-without-source.jar -DgroupId=com.example -DartifactId=jar-without-source -Dpackaging=jar -Dversion=1.0` And then you can depend on it in your pom.xml using the groupId and artifactId as you would a published jar. Installing this jar could be a required step for any system to build the project - or if you have a organization internal shared repo (ex: Nexus), you can deploy it there – Stan Kurdziel Dec 30 '16 at 21:49
  • @paterh (or anyone else) If you really don't want to replace all local jars with maven dependencies, then perhaps system scope works for you. It won't result in a "clean" maven project and should not be part of general recommendations. -- I believe it would also be possible to create a project that contains a jar and installs it to the local repo before depending on it, so that `git clone ...; mvn clean install` works; However, it's probably no better than system scope. When I use maven, I keep jars out of source control. I believe this is the intended best practice and has served me well – Stan Kurdziel Dec 30 '16 at 22:08
  • Updated link to @PascalThivent 's documentation on [Dependency Scopes](https://web.archive.org/web/20150119194524/http://docs.codehaus.org:80/display/MAVENUSER/Dependency+Scopes) – Greg Chabala Dec 13 '17 at 16:11
65

You may create local repository on your project

For example if you have libs folder in project structure

  • In libs folder you should create directory structure like: /groupId/artifactId/version/artifactId-version.jar

  • In your pom.xml you should register repository

    <repository>
        <id>ProjectRepo</id>
        <name>ProjectRepo</name>
        <url>file://${project.basedir}/libs</url>
    </repository>
    
  • and add dependency as usual

    <dependency>
        <groupId>groupId</groupId>
        <artifactId>artifactId</artifactId>
        <version>version</version>
    </dependency>
    

That is all.

For detailed information: How to add external libraries in Maven

Fırat KÜÇÜK
  • 4,536
  • 1
  • 42
  • 52
Dmytro Boichenko
  • 4,517
  • 3
  • 25
  • 31
30

Note: When using the System scope (as mentioned on this page), Maven needs absolute paths.

If your jars are under your project's root, you'll want to prefix your systemPath values with ${basedir}.

Community
  • 1
  • 1
Ed Brannin
  • 7,033
  • 2
  • 25
  • 32
15

This is what I have done, it also works around the package issue and it works with checked out code.

I created a new folder in the project in my case I used repo, but feel free to use src/repo

In my POM I had a dependency that is not in any public maven repositories

<dependency>
    <groupId>com.dovetail</groupId>
    <artifactId>zoslog4j</artifactId>
    <version>1.0.1</version>
    <scope>runtime</scope>
</dependency>

I then created the following directories repo/com/dovetail/zoslog4j/1.0.1 and copied the JAR file into that folder.

I created the following POM file to represent the downloaded file (this step is optional, but it removes a WARNING) and helps the next guy figure out where I got the file to begin with.

<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.dovetail</groupId>
    <artifactId>zoslog4j</artifactId>
    <packaging>jar</packaging>
    <version>1.0.1</version>
    <name>z/OS Log4J Appenders</name>
    <url>http://dovetail.com/downloads/misc/index.html</url>
    <description>Apache Log4j Appender for z/OS Logstreams, files, etc.</description>
</project>

Two optional files I create are the SHA1 checksums for the POM and the JAR to remove the missing checksum warnings.

shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar \
          > repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar.sha1

shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom \
          > repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom.sha1

Finally I add the following fragment to my pom.xml that allows me to refer to the local repository

<repositories>
    <repository>
        <id>project</id>
        <url>file:///${basedir}/repo</url>
    </repository>
</repositories>
Betlista
  • 9,561
  • 10
  • 62
  • 99
Archimedes Trajano
  • 22,850
  • 10
  • 113
  • 154
  • Hi, did you put the pom files in the local repository or next to your jar files? – Peymankh May 08 '12 at 11:55
  • In the above solution it was next to the JAR files. Mind you I don't like the solution above because it is too much work. – Archimedes Trajano May 08 '12 at 12:58
  • I still prefer the solution I posted here http://stackoverflow.com/questions/2229757/maven-add-a-dependency-to-a-jar-by-relative-path/7908872#7908872 – Archimedes Trajano May 08 '12 at 13:02
  • I like this approach, although I used the [maven install plugin](https://maven.apache.org/plugins/maven-install-plugin/examples/specific-local-repo.html) to automate installing the jar into the local repo. – Carl G Jan 12 '16 at 11:27
13

This is how we add or install a local jar

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>iamajar</artifactId>
        <version>1.0</version>
        <scope>system</scope>
        <systemPath>${project.basedir}/lib/iamajar.jar</systemPath>
    </dependency>

i gave some default groupId and artifactId because they are mandatory :)

Betlista
  • 9,561
  • 10
  • 62
  • 99
Praneel PIDIKITI
  • 15,781
  • 13
  • 36
  • 59
13

You really ought to get a framework in place via a repository and identifying your dependencies up front. Using the system scope is a common mistake people use, because they "don't care about the dependency management." The trouble is that doing this you end up with a perverted maven build that will not show maven in a normal condition. You would be better off following an approach like this.

Brian Fox
  • 6,324
  • 3
  • 25
  • 31
10

Maven install plugin has command line usage to install a jar into the local repository, POM is optional but you will have to specify the GroupId, ArtifactId, Version and Packaging (all the POM stuff).

n00begon
  • 3,467
  • 3
  • 26
  • 41
toad
  • 1,353
  • 8
  • 14
8

Using <scope>system</scope> is a terrible idea for reasons explained by others, installing the file manually to your local repository makes the build unreproducible, and using <url>file://${project.basedir}/repo</url> is not a good idea either because (1) that may not be a well-formed file URL (e.g. if the project is checked out in a directory with unusual characters), (2) the result is unusable if this project’s POM is used as a dependency of someone else’s project.

Assuming you are unwilling to upload the artifact to a public repository, Simeon’s suggestion of a helper module does the job. But there is an easier way now…

The Recommendation

Use non-maven-jar-maven-plugin. Does exactly what you were asking for, with none of the drawbacks of the other approaches.

Jesse Glick
  • 22,072
  • 9
  • 77
  • 100
  • Also saw [maven-external-dependency-plugin](https://code.google.com/p/maven-external-dependency-plugin/) though non-maven-jar-maven-plugin seems more straightforward to use. – Jesse Glick Aug 10 '13 at 12:02
8

I found another way to do this, see here from a Heroku post

To summarize (sorry about some copy & paste)

  • Create a repo directory under your root folder:
yourproject
+- pom.xml
+- src
+- repo
  • Run this to install the jar to your local repo directory
mvn deploy:deploy-file -Durl=file:///path/to/yourproject/repo/ -Dfile=mylib-1.0.jar -DgroupId=com.example -DartifactId=mylib -Dpackaging=jar -Dversion=1.0
  • Add this your pom.xml:
<repositories>
    <!--other repositories if any-->
    <repository>
        <id>project.local</id>
        <name>project</name>
        <url>file:${project.basedir}/repo</url>
    </repository>
</repositories>


<dependency>
    <groupId>com.example</groupId>
    <artifactId>mylib</artifactId>
    <version>1.0</version>  
</dependency>
xbeta
  • 2,187
  • 4
  • 26
  • 47
7

What seems simplest to me is just configure your maven-compiler-plugin to include your custom jars. This example will load any jar files in a lib directory.

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <includes>
                    <include>lib/*.jar</include>
                </includes>
            </configuration>
        </plugin>
realgt
  • 1,675
  • 15
  • 12
6

After having really long discussion with CloudBees guys about properly maven packaging of such kind of JARs, they made an interesting good proposal for a solution:

Creation of a fake Maven project which attaches a pre-existing JAR as a primary artifact, running into belonged POM install:install-file execution. Here is an example of such kinf of POM:

 <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <version>2.3.1</version>
            <executions>
                <execution>
                    <id>image-util-id</id>
                    <phase>install</phase>
                    <goals>
                        <goal>install-file</goal>
                    </goals>
                    <configuration>
                        <file>${basedir}/file-you-want-to-include.jar</file>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>${project.artifactId}</artifactId>
                        <version>${project.version}</version>
                        <packaging>jar</packaging>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

But in order to implement it, existing project structure should be changed. First, you should have in mind that for each such kind of JAR there should be created different fake Maven project (module). And there should be created a parent Maven project including all sub-modules which are : all JAR wrappers and existing main project. The structure could be :

root project (this contains the parent POM file includes all sub-modules with module XML element) (POM packaging)

JAR 1 wrapper Maven child project (POM packaging)

JAR 2 wrapper Maven child project (POM packaging)

main existing Maven child project (WAR, JAR, EAR .... packaging)

When parent running via mvn:install or mvn:packaging is forced and sub-modules will be executed. That could be concerned as a minus here, since project structure should be changed, but offers a non static solution at the end

Community
  • 1
  • 1
Simeon Angelov
  • 430
  • 3
  • 18
  • Just an observation, but I don't think you need to create a new POM for each JAR you want to add. It should be enough to create a single POM to add all of the JARs providing you have a execution block for *each* jar you want to add. You just need to make sure that each block has a unique id. The result is a single Maven module that will add all the JARs into the local repo. (Just make sure that the maven coordinates don't clash with anything that might already be there or might be added later!) – Stormcloud Feb 11 '14 at 10:05
  • Hero. This is EXACTLY what I wanted. Nice one fella. 2013 must have been a good year ;) – ndtreviv Jan 26 '16 at 13:28
4

The problem with systemPath is that the dependencies' jars won't get distributed along your artifacts as transitive dependencies. Try what I've posted here: Is it best to Mavenize your project jar files or put them in WEB-INF/lib?

Then declare dependencies as usual.

And please read the footer note.

Community
  • 1
  • 1
Martín Schonaker
  • 7,022
  • 4
  • 28
  • 55
3

A quick&dirty batch solution (based on Alex's answer):

libs.bat

@ECHO OFF
FOR %%I IN (*.jar) DO (
echo ^<dependency^>
echo ^<groupId^>local.dummy^</groupId^>
echo ^<artifactId^>%%I^</artifactId^>
echo ^<version^>0.0.1^</version^>
echo ^<scope^>system^</scope^>
echo ^<systemPath^>${project.basedir}/lib/%%I^</systemPath^>
echo ^</dependency^>
)

Execute it like this: libs.bat > libs.txt. Then open libs.txt and copy its content as dependencies.

In my case, I only needed the libraries to compile my code, and this solution was the best for that purpose.

lmiguelmh
  • 2,259
  • 27
  • 46
3

A strange solution I found:

using Eclipse

  • create simple (non-maven) java project
  • add a Main class
  • add all the jars to the classpath
  • export Runnable JAR (it's important, because no other way here to do it)
  • select Extract required libraries into generated JAR
  • decide the licence issues
  • tadammm...install the generated jar to your m2repo
  • add this single dependency to your other projects.

cheers, Balint

Balint Pato
  • 1,418
  • 1
  • 13
  • 26
3

If you want a quick and dirty solution, you can do the following (though I do not recommend this for anything except test projects, maven will complain in length that this is not proper).

Add a dependency entry for each jar file you need, preferably with a perl script or something similar and copy/paste that into your pom file.

#! /usr/bin/perl

foreach my $n (@ARGV) {

    $n=~s@.*/@@;

    print "<dependency>
    <groupId>local.dummy</groupId>
    <artifactId>$n</artifactId>
    <version>0.0.1</version>
    <scope>system</scope>
    <systemPath>\${project.basedir}/lib/$n</systemPath>
</dependency>
";
Betlista
  • 9,561
  • 10
  • 62
  • 99
Alex Lehmann
  • 578
  • 4
  • 11
  • Yes this is exactly what I was looking for. A way to push it through for research test code. Nothing fancy. Yeah I know that that's what they all say :) The various maven plugin solutions seem to be overkill for my purposes. I have some jars that were given to me as 3rd party libs with a pom file. I want it to compile/run quickly. This solution which I trivially adapted to python worked wonders for me. Cut and pasted into my pom. – Paul Feb 12 '14 at 20:26
2

Even though it does not exactly fit to your problem, I'll drop this here. My requirements were:

  1. Jars that can not be found in an online maven repository should be in the SVN.
  2. If one developer adds another library, the other developers should not be bothered with manually installing them.
  3. The IDE (NetBeans in my case) should be able find the sources and javadocs to provide autocompletion and help.

Let's talk about (3) first: Just having the jars in a folder and somehow merging them into the final jar will not work for here, since the IDE will not understand this. This means all libraries have to be installed properly. However, I dont want to have everyone installing it using "mvn install-file".

In my project I needed metawidget. Here we go:

  1. Create a new maven project (name it "shared-libs" or something like that).
  2. Download metawidget and extract the zip into src/main/lib.
  3. The folder doc/api contains the javadocs. Create a zip of the content (doc/api/api.zip).
  4. Modify the pom like this
  5. Build the project and the library will be installed.
  6. Add the library as a dependency to your project, or (if you added the dependency in the shared-libs project) add shared-libs as dependency to get all libraries at once.

Every time you have a new library, just add a new execution and tell everyone to build the project again (you can improve this process with project hierachies).

n00begon
  • 3,467
  • 3
  • 26
  • 41
Cephalopod
  • 13,262
  • 6
  • 43
  • 65
  • You might want to check [Maven: add a dependency to a jar by relative path](http://stackoverflow.com/questions/2229757/maven-add-a-dependency-to-a-jar-by-relative-path/2230464#2230464) (which is IMHO a better alternative). – Pascal Thivent Sep 18 '10 at 19:43
  • It is better if you can ensure that the local repository always has the same relative path to the project. If I have many projects (or different branches) in different locations this will not work. – Cephalopod Sep 19 '10 at 11:51
  • [My answer](http://stackoverflow.com/questions/364114/can-i-add-jars-to-maven-2-build-classpath-without-installing-them/426176#426176) has a way to tell pom.xml about a jar inside your project. Why not just do that, and point it to jars in ${basedir}/lib? – Ed Brannin Sep 20 '10 at 17:36
  • 1
    @Ed Because that's absolutely not what the system scope is for, system scoped dependencies have lots of side effects. This is an horrible practice that should be totally banned. – Pascal Thivent Sep 21 '10 at 19:13
2

To install the 3rd party jar which is not in maven repository use maven-install-plugin.

Below are steps:

  1. Download the jar file manually from the source (website)
  2. Create a folder and place your jar file in it
  3. Run the below command to install the 3rd party jar in your local maven repository

mvn install:install-file -Dfile= -DgroupId= -DartifactId= -Dversion= -Dpackaging=

Below is the e.g one I used it for simonsite log4j

mvn install:install-file -Dfile=/Users/athanka/git/MyProject/repo/log4j-rolling-appender.jar -DgroupId=uk.org.simonsite -DartifactId=log4j-rolling-appender -Dversion=20150607-2059 -Dpackaging=jar

  1. In the pom.xml include the dependency as below

      <dependency> 
            <groupId>uk.org.simonsite</groupId>
            <artifactId>log4j-rolling-appender</artifactId>
            <version>20150607-2059</version> 
      </dependency>
    
  2. Run the mvn clean install command to create your packaging

Below is the reference link:

https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

atr
  • 505
  • 4
  • 9
  • This is a borderline [link-only answer](//meta.stackexchange.com/q/8231). You should expand your answer to include as much information here, and use the link only for reference. – Goodbye StackExchange Oct 06 '16 at 21:27
2

For those that didn't find a good answer here, this is what we are doing to get a jar with all the necessary dependencies in it. This answer (https://stackoverflow.com/a/7623805/1084306) mentions to use the Maven Assembly plugin but doesn't actually give an example in the answer. And if you don't read all the way to the end of the answer (it's pretty lengthy), you may miss it. Adding the below to your pom.xml will generate target/${PROJECT_NAME}-${VERSION}-jar-with-dependencies.jar

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <!-- MainClass in mainfest make a executable jar -->
                <archive>
                  <manifest>
                    <mainClass>my.package.mainclass</mainClass>
                  </manifest>
                </archive>

            </configuration>
            <executions>
              <execution>
                <id>make-assembly</id>
                <!-- bind to the packaging phase -->
                <phase>package</phase> 
                <goals>
                    <goal>single</goal>
                </goals>
              </execution>
            </executions>
        </plugin>
Community
  • 1
  • 1
Donovan
  • 816
  • 2
  • 10
  • 16
1

I alluded to some python code in a comment to the answer from @alex lehmann's , so am posting it here.

def AddJars(jarList):
  s1 = ''
  for elem in jarList:
   s1+= """
     <dependency>
        <groupId>local.dummy</groupId>
        <artifactId>%s</artifactId>
        <version>0.0.1</version>
        <scope>system</scope>
        <systemPath>${project.basedir}/manual_jars/%s</systemPath>
     </dependency>\n"""%(elem, elem)
  return s1
Paul
  • 6,257
  • 7
  • 35
  • 39
0

I just wanted a quick and dirty workaround... I couldn't run the script from Nikita Volkov: syntax error + it requires a strict format for the jar names.

I made this Perl script which works with whatever format for the jar file names, and it generates the dependencies in an xml so it can be copy pasted directly in a pom.

If you want to use it, make sure you understand what the script is doing, you may need to change the lib folder and the value for the groupId or artifactId...

#!/usr/bin/perl

use strict;
use warnings;

open(my $fh, '>', 'dependencies.xml') or die "Could not open file 'dependencies.xml' $!";
foreach my $file (glob("lib/*.jar")) {
    print "$file\n";
    my $groupId = "my.mess";
    my $artifactId = "";
    my $version = "0.1-SNAPSHOT";
    if ($file =~ /\/([^\/]*?)(-([0-9v\._]*))?\.jar$/) {
        $artifactId = $1;
        if (defined($3)) {
            $version = $3;
        }
        `mvn install:install-file -Dfile=$file -DgroupId=$groupId -DartifactId=$artifactId -Dversion=$version -Dpackaging=jar`;
        print $fh "<dependency>\n\t<groupId>$groupId</groupId>\n\t<artifactId>$artifactId</artifactId>\n\t<version>$version</version>\n</dependency>\n";
        print " => $groupId:$artifactId:$version\n";
    } else {
        print "##### BEUH...\n";
    }
}
close $fh;
boumbh
  • 1,781
  • 16
  • 20
0

This doesn't answer how to add them to your POM, and may be a no brainer, but would just adding the lib dir to your classpath work? I know that is what I do when I need an external jar that I don't want to add to my Maven repos.

Hope this helps.

javamonkey79
  • 16,837
  • 35
  • 104
  • 166
0

The solution for scope='system' approach in Java:

public static void main(String[] args) {
        String filepath = "/Users/Downloads/lib/";
        try (Stream<Path> walk = Files.walk(Paths.get(filepath))) {

        List<String> result = walk.filter(Files::isRegularFile)
                .map(x -> x.toString()).collect(Collectors.toList());

                String indentation = "    ";
                for (String s : result) {
                    System.out.println(indentation + indentation + "<dependency>");
                    System.out.println(indentation + indentation + indentation + "<groupId>"
                            + s.replace(filepath, "").replace(".jar", "")
                            + "</groupId>");
                    System.out.println(indentation + indentation + indentation + "<artifactId>"
                            + s.replace(filepath, "").replace(".jar", "")
                            + "</artifactId>");
                    System.out.println(indentation + indentation + indentation + "<version>"
                            + s.replace(filepath, "").replace(".jar", "")
                            + "</version>");
                    System.out.println(indentation + indentation + indentation + "<scope>system</scope>");
                    System.out.println(indentation + indentation + indentation + "<systemPath>" + s + "</systemPath>");
                    System.out.println(indentation + indentation + "</dependency>");
                }

    } catch (IOException e) {
        e.printStackTrace();
    }
}
Oleksii Kyslytsyn
  • 2,048
  • 2
  • 24
  • 37
0

What works in our project is what Archimedes Trajano wrote, but we had in our .m2/settings.xml something like this:

 <mirror>
  <id>nexus</id>
  <mirrorOf>*</mirrorOf>
  <url>http://url_to_our_repository</url>
 </mirror>

and the * should be changed to central. So if his answer doesn't work for you, you should check your settings.xml

Betlista
  • 9,561
  • 10
  • 62
  • 99