31

Maven is great. It mostly keeps me out of jar dependency hell by specifying versions of dependent packages in the pom configuration, and applies them automatically. It also has great integration with Eclipse via m2e, so that things work seamlessly in an IDE.

This is all great for dependencies that are globally known to Maven. However, sometimes, there are libraries that need to be included in a project that is not available in the Maven repos. In this case, I usually add them to a lib/ directory in my project. As long as they are in the classpath then things compile.

However, the problem is getting them to be included automatically when importing a project. I've been tolerating this problem with half-baked fixes and hacks for far too long. Every time someone installs this project, I have to tell them to manually add the jars in lib/ to their Eclipse build path so that all the errors go away. Something like the following:

enter image description here

I'm searching for a way to automate this process in a way that works with both the mvn command line program and Eclipse: more an emphasis on Eclipse, because it's nice to have projects that just compile when you import them.

I don't want to set up a repo server for this, nor do I have any in-house proprietary components that would warrant setting up anything locally. I just have some jar files where the developers don't use Maven; and I want to compile with them...I should just be able to include them in the distribution of my software, right?

I'm really looking for a reasonable way to implement this that will also work in Eclipse with no fuss. This is one solution I've found promising, but there definitely doesn't seem to be an authoritative solution to this problem. The only other thing that comes close is the maven-addjars-plugin, which works okay but only on the commandline. This plugin is not bad, and has a pretty reasonable configuration:

<plugin>
    <groupId>com.googlecode.addjars-maven-plugin</groupId>
    <artifactId>addjars-maven-plugin</artifactId>
    <version>1.0.5</version>
    <executions>
        <execution>
            <goals>
                <goal>add-jars</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>${project.basedir}/lib/java-aws-mturk</directory>
                    </resource>
                    <resource>
                        <directory>${project.basedir}/lib/not-in-maven</directory>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

However, trying to get it to run in Eclipse involves adding the following mess about lifecycle mapping to your pom.xml, which I have never gotten to work; I don't even think it is configured to actually add anything to the Eclipse build path.

<pluginManagement>
    <plugins>
        <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
        <plugin>
            <groupId>org.eclipse.m2e</groupId>
            <artifactId>lifecycle-mapping</artifactId>
            <version>1.0.0</version>
            <configuration>
                <lifecycleMappingMetadata>
                    <pluginExecutions>
                        <pluginExecution>
                            <pluginExecutionFilter>
                                <groupId>
                                    com.googlecode.addjars-maven-plugin
                                </groupId>
                                <artifactId>
                                    addjars-maven-plugin
                                </artifactId>
                                <versionRange>
                                    [1.0.5,)
                                </versionRange>
                                <goals>
                                    <goal>add-jars</goal>
                                </goals>
                            </pluginExecutionFilter>
                            <action>
                                <execute />
                            </action>
                        </pluginExecution>
                    </pluginExecutions>
                </lifecycleMappingMetadata>
            </configuration>
        </plugin>
    </plugins>
</pluginManagement>
Andrew Mao
  • 35,740
  • 23
  • 143
  • 224
  • 1
    I'd prefer relying on a local nexus installation. – guido Mar 09 '13 at 00:29
  • 1
    I want to be able to give this software to others to use, so that seems unreasonable. It's just a few jars that I want to share, so it shouldn't be that complicated. – Andrew Mao Mar 09 '13 at 00:32
  • Nexus (or any other repo implementation) would help your build process, so it would not be needed for your users; while if you are FOSS, maven-izing other's libraries and sending patches upstream would contribute to the community. Anyway, your choice. – guido Mar 09 '13 at 02:23
  • I don't need it for users; I need it for other people who check out the code on github. I have some plugins and code (some from closed source) that it is not feasible to maven-ize, and it's not reasonable to expect to be able to do that for every dependency. – Andrew Mao Mar 09 '13 at 05:48
  • Refer this https://stackoverflow.com/a/45120371/1709793 – craftsmannadeem Jul 15 '17 at 16:27

3 Answers3

67

1) you can use system scope dependency

    <dependency>
        <groupId>test</groupId>
        <artifactId>x</artifactId>
        <version>1.0</version>
        <scope>system</scope>
        <systemPath>${basedir}/lib/x.jar</systemPath>
    </dependency>

2) you can copy your x.jar to local maven repository as

repository/test/x/1.0/x-1.0.jar

and add a dependency as

    <dependency>
        <groupId>test</groupId>
        <artifactId>x</artifactId>
        <version>1.0</version>
    </dependency>
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 1
    That's EXACTLY what I needed. It also makes the jars available for projects dependent on this one. Integrates perfectly with Eclipse and avoids all this managing-repo and XML that everyone else is suggesting. Also doesn't involve copying crap into Maven repositories. +100 upvotes if I could. – Andrew Mao Mar 09 '13 at 06:25
  • 1
    @Andrew Mao Fine if this solution works for you. Beware of the fact, that [system scope dependencies are similar to "provided" dependencies](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope). Thus they are expected to exist on a target platform and will not be included in the packaged artifact (e.g. war file). – FrVaBe Mar 09 '13 at 09:38
  • 2
    I've found the system scope to influence the handling of transient dependencies further downstream and we could not use it. I believe the proper way is to install (manually or scripted) the artifacts you need in your local repository. – Thorbjørn Ravn Andersen Aug 09 '13 at 11:42
  • If I use the system scope, are the `groupId` and `artifactId` even relevant? (i.e. can I just put whatever in those fields?) As these jars aren't in Maven repos, I'm assuming they don't matter? – Kenny Worden Jul 28 '15 at 01:20
  • They can be anything but empy – Evgeniy Dorofeev Jul 28 '15 at 02:06
  • Anyone reading this QA might want to look at [this answer](http://stackoverflow.com/questions/364114/can-i-add-jars-to-maven-2-build-classpath-without-installing-them) before trying any of the approaches mentioned here. – Akshay Damle Feb 15 '17 at 08:43
  • Very useful for me! Thanks a lot! – FilippoG Apr 24 '18 at 10:33
6

You can use maven to install files from a project\lib folder to the local repo with the maven-install-plugin as below. I have done this before with JDBC drivers. You might have to create a separate pom for it and execute it with mvn -f installdeps.pom or something like that.

If you can get it to play nice and bind with a lifecycle like validate or something, then you can use the m2e plugin with Eclipse and it just might play nice and read dependencies straight from the pom.xml and install the jars as needed to the local repo.

    <plugin>
        <!-- We dont want children attempting to install these jars to the repo. -->
        <inherited>false</inherited>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-install-plugin</artifactId>
        <executions>
            <execution>
                <id>Microsoft JDBC Driver File 1</id>
                <phase>install</phase>
                <goals>
                    <goal>install-file</goal>
                </goals>
                <configuration>
                    <file>lib/sqljdbc4.jar</file>
                    <groupId>com.microsoft</groupId>
                    <artifactId>microsoft-jdbc-driver</artifactId>
                    <version>4.0</version>
                    <packaging>jar</packaging>
                </configuration>
            </execution>
            <execution>
                <id>ojdbc5</id>
                <phase>install</phase>
                <goals>
                    <goal>install-file</goal>
                </goals>
                <configuration>
                    <file>lib/ojdbc5.jar</file>
                    <groupId>com.oracle</groupId>
                    <artifactId>ojdbc5</artifactId>
                    <version>11.1.2</version>
                    <packaging>jar</packaging>
                </configuration>
            </execution>
        </executions>
    </plugin>
Javanator
  • 109
  • 6
0

It seems to me that you could use the Maven Resources Plugin to do this for you. Just bind copying of resources to an appropriate lifecycle phase (a phase prior to compilation). You'll most likely need to tweak the maven-compiler-plugin so that these libraries are on the classpath when compiling and at runtime.

Muel
  • 4,309
  • 1
  • 23
  • 32