72

I am using maven-assembly plugin to create a jar of my application, including its dependencies as follows:

<assembly>
    <id>macosx</id>
    <formats>
       <format>tar.gz</format>
       <format>dir</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <includes>
                <include>*:jar</include>
            </includes>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
</assembly>

(I omitted some other stuff that is not related to the question)

So far this has worked fine because it creates a lib directory with all dependencies. However, I recently added a new dependency whose scope is system, and it does not copy it to the lib output directory. i must be missing something basic here, so I call for help.

The dependency that I just added is:

<dependency>
  <groupId>sourceforge.jchart2d</groupId>
  <artifactId>jchart2d</artifactId>
  <version>3.1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/external/jchart2d-3.1.0.jar</systemPath>
</dependency>

The only way I was able to include this dependency was by adding the following to the assembly element:

<files>
    <file>
        <source>external/jchart2d-3.1.0.jar</source>
        <outputDirectory>lib</outputDirectory>
    </file>
</files>

However, this forces me to change the pom and the assembly file whenever this jar is renamed, if ever. Also, it seems just wrong.

I have tried with <scope>runtime</scope> in the dependencySets and <include>sourceforge.jchart2d:jchart2d</include> with no luck.

So how do you include a system scoped jar to your assembly file in maven 2?

Thanks a lot

YuppieNetworking
  • 8,672
  • 7
  • 44
  • 65

7 Answers7

96

I'm not surprised that system scope dependencies are not added (after all, dependencies with a system scope must be explicitly provided by definition). Actually, if you really don't want to put that dependency in your local repository (for example because you want to distribute it as part of your project), this is what I would do:

  • I would put the dependency in a "file system repository" local to the project.
  • I would declare that repository in my pom.xml like this:

    <repositories>
      <repository>
        <id>my</id>
        <url>file://${basedir}/my-repo</url>
      </repository>
    </repositories>
    
  • I would just declare the artifact without the system scope, this is just a source of troubles:

    <dependency>
      <groupId>sourceforge.jchart2d</groupId>
      <artifactId>jchart2d</artifactId>
      <version>3.1.0</version>
    </dependency>
    

I'm not 100% sure this will suit your needs but I think it's a better solution than using the system scope.

Update: I should have mentioned that in my original answer and I'm fixing it now. To install a third party library in the file-based repository, use install:install-file with the localRepositoryPath parameter:

mvn install:install-file -Dfile=<path-to-file> \
                         -DgroupId=<myGroup> \
                         -DartifactId=<myArtifactId> \
                         -Dversion=<myVersion> \
                         -Dpackaging=<myPackaging> \
                         -DlocalRepositoryPath=<path-to-my-repo>

You can paste this as is in a *nix shell. On windows, remove the "\" and put everything on a single line.

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 2
    It did work, but it was not a trivial task to install the file in a local repo different than $HOME/.m2/repository. I had to do a mvn install:install-file [...install-file options...] -Dmaven.repo.local=path_to_my_local_repo which forced maven to download its most basic plugins. Could you suggest how to install files to this local repo? – YuppieNetworking Jan 15 '10 at 13:43
  • I should have mentioned that :) I would have installed the artifact in the local repo (`~/.m2/repository`) with `install:install-file` and then moved the directory tree to `${basedir}/my-repo`. I'd just delete unwanted stuff from `${basedir}/my-repo` in your case. – Pascal Thivent Jan 15 '10 at 14:16
  • Yes, I eventually did that... it's not pretty, but it works. Thanks a lot. – YuppieNetworking Jan 15 '10 at 15:27
27

Btw you can automate it and make it a part of your maven build. The following will install your jar into your local repository before compilation:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <executions>
                <execution>
                    <id>hack-binary</id>
                    <phase>validate</phase>
                    <configuration>
                        <file>${basedir}/lib/your-lib.jar</file>
                        <repositoryLayout>default</repositoryLayout>
                        <groupId>your-group</groupId>
                        <artifactId>your-artifact</artifactId>
                        <version>0.1</version>
                        <packaging>jar</packaging>
                        <generatePom>true</generatePom>
                    </configuration>
                    <goals>
                        <goal>install-file</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
alx
  • 287
  • 3
  • 2
  • 3
    Doesn't it support installling multiple files at once? – Tuukka Mustonen Sep 22 '10 at 16:04
  • Wow, this is very nice! thank you so much! @Tuukka Mustonen you have to copy the ... part for each file – timaschew Sep 25 '11 at 13:35
  • 11
    Unfortunately this doesn't work. I came to this solution as well, thinking it seemed the easiest, however Maven requires all dependencies to be resolved _before_ executing plugins bound to the `validate` phase (which precedes `compile`, etc...). Thus once the artifact is installed, this will re-install it, but it will not do an initial install - it's a chicken/egg problem. One _could_ bind this to the `clean` phase (as that does not require dependency resolution first) and tell developers to first run `mvn clean`, but then it no longer works using "standard procedures" out of the box. – Chadwick Oct 12 '11 at 18:35
  • @Chadwick simply binding it to the clean phase doesn't work. I have a project that builds (and cleans) fine, but does not even enter the clean phase on other environments because of resolution errors. Only temporarily changing the scope of dependencies to allow an install seems to help. – Amani Kilumanga Aug 24 '16 at 04:07
  • 2
    Binding to `initialize` works for me. My IDE complains about unresolved dependency, but when I run it, the local JAR file gets installed every time and then resolved just fine. Brilliant solution @alx ! – diginoise May 04 '17 at 08:12
18

I find easy solution in case you creating jar

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-war-plugin</artifactId>
  <version>2.1.1</version>
  <configuration>
    <webResources>
    <resource>
      <directory>dependencies/mydep</directory>
        <targetPath>WEB-INF/lib</targetPath>
        <filtering>true</filtering>
        <includes>
           <include>**/*.jar</include>
        </includes>
    </resource>
  </webResources>
</configuration>
</plugin>
mc.dev
  • 2,675
  • 3
  • 21
  • 27
5

You can also handle this via adding a supplemental dependencySet in your dependencySets.

<dependencySet>
  <scope>system</scope>
  <includes>
    <include>*:jar</include>
  </includes>
  <outputDirectory>lib</outputDirectory>
</dependencySet>

The best thing would be to use a Repository Manager (like Nexus, Artifactory, Archiva) and install this kind of dependency in a particular repository. After that you can use such things as a simple dependency. This will simplify your life.

Docs:

forkdbloke
  • 1,505
  • 2
  • 12
  • 29
khmarbaise
  • 92,914
  • 28
  • 189
  • 235
3

Edited: Sorry that i didn't realize alx also mentioned about the clean life cycle workaround.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-install-plugin</artifactId>
    <executions>
        <execution>
            <id>hack-binary</id>
            <phase>clean</phase>
            <configuration>
                <file>${basedir}/lib/your-lib.jar</file>
                <repositoryLayout>default</repositoryLayout>
                <groupId>your-group</groupId>
                <artifactId>your-artifact</artifactId>
                <version>0.1</version>
                <packaging>jar</packaging>
                <generatePom>true</generatePom>
            </configuration>
            <goals>
                <goal>install-file</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Base on the solution provided by alx, you can execute the install file step at clean phase. but since the clean phase is not in the default life cycle, you have to execute mvn clean at the first time to ensure the jar is ready in the local repo.

ex: mvn clean; mvn package

ykyuen
  • 225
  • 2
  • 3
2

A simple solution for this is to add it into local maven repository

One way to do is via mvn install commands as suggested in previous post .

Another easy way is , 1) In your eclipse ide right click on project select Maven option . 2) Select Install or deploy an artifact to a maven repository option and click on next. 3)Click on browse next to the Artifact file checkbox & select your jar file 4)Enter the GroupId and ArtifactId and version ensure generate pom & create checksum are checked & packaging is jar

Click on finish and that's it ! Your job is done the jar is added in your local repository which you can define in setting.xml or m2 directory

Now just add the simple maven dependency as per the GroupId,ArtifactId & jar version that you have entered as per the import and that's it your external jar will be packaged by maven.

bonnal-enzo
  • 1,165
  • 9
  • 19
  • Thanks for the help. It worked great for me and it's definitely easier than the other ways given here. Cheers :) – Nav Oct 26 '15 at 14:43
1

it has worked in a easier way on my solution :

remove from your dependency :

<dependency>
  <groupId>tiago.medici</groupId>
  <artifactId>eureka</artifactId>
  <version>0.0.1</version>
</dependency> 

Then add the maven-install-plugin in the pom.xml as well.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-install-plugin</artifactId>
  <executions>
    <execution>
      <id>install-external</id>
      <phase>clean</phase>
      <configuration>
        <file>${basedir}/external/tiago.medici-0.0.1.jar</file>
        <repositoryLayout>default</repositoryLayout>
        <groupId>tiago.medici</groupId>
        <artifactId>eureka</artifactId>
        <version>0.0.1</version>
        <packaging>jar</packaging>
        <generatePom>true</generatePom>
      </configuration>
      <goals>
        <goal>install-file</goal>
      </goals>
    </execution>
  </executions>
</plugin>
Tiago Medici
  • 1,944
  • 22
  • 22