How To: Eclipse Maven install build jar with dependencies

82,527

There are a couple of ways of doing this.

1) If you want an uber-jar (repacked with all dependencies), look into using and configuring the maven-shade-plugin:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.6</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>com.group.id.Launcher1</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

This will unpack all dependencies and merge them into one JAR file.


2) If you want to deliver a bundle (zip, tar.gz, etc) with the unpacked JAR files in the bundle (perhaps under lib/) then you need to look into the maven-assembly-plugin:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.3</version>
        <executions>
          <execution>
            <id>create-distro</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <descriptors>
                <descriptor>src/main/assembly/dist.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Note that this requires an assembly descriptor src/main/assembly/dist.xml and example looks like this:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0">
  <id>distribution</id>
  <formats>
    <format>zip</format>
  </formats>

  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <useTransitiveDependencies>false</useTransitiveDependencies>
      <unpack>false</unpack>
      <scope>runtime</scope>
      <fileMode>0755</fileMode>
      <directoryMode>0755</directoryMode>
      <outputDirectory>bin</outputDirectory>

      <includes>
        <include>com.group.id:project-launch1</include>
        <include>com.group.id:project-launch2</include>
      </includes>

    </dependencySet>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <useTransitiveDependencies>true</useTransitiveDependencies>
      <unpack>false</unpack>
      <scope>runtime</scope>
      <fileMode>0644</fileMode>
      <directoryMode>0755</directoryMode>
      <outputDirectory>lib</outputDirectory>

      <includes>
        <include>com.group.id:project-lib1</include>
        <include>com.group.id:project-lib2</include>
        <include>com.group.id:project-lib3</include>
        <include>com.group.id:project-lib4</include>
      </includes>

    </dependencySet>
  </dependencySets>
</assembly>

And since you are now assembling dependencies, you have better define the dependency in the pom.xml, like so:

  <dependencies>
    <dependency>
      <groupId>com.group.id</groupId>
      <artifactId>project-launch1</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.group.id</groupId>
      <artifactId>project-launch2</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.group.id</groupId>
      <artifactId>project-lib1</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    ... and so on ...
  </dependencies>


3) If you are delivering a bundle with an executable JAR file launcher, you will likely need to add a maven-jar-plugin configuration in addition to the maven-assembly-plugin:

  <dependencies>
    <dependency>
      <groupId>com.group.id</groupId>
      <artifactId>project-lib1</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.group.id</groupId>
      <artifactId>project-lib2</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.group.id</groupId>
      <artifactId>project-lib3</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <type>jar</type>
    </dependency>
    ... and so on ...
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <addMavenDescriptor>false</addMavenDescriptor>
            <compress>true</compress>
            <manifest>
              <mainClass>com.group.id.Launcher1</mainClass>
              <addClasspath>true</addClasspath>
              <classpathPrefix>../lib/</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

Note that the "addClasspath" directive adds the project dependencies to the class path. This is needed for JAR launchers, as they explicitly ignore all CLASSPATH environmental variables.

Share:
82,527
Alex
Author by

Alex

Updated on July 09, 2022

Comments

  • Alex
    Alex almost 2 years

    I am using Eclipse Maven (m2e) inside Eclipse and I am running my project like this:

    My pom.xml looks like this:

    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>ro.project</groupId>
        <packaging>jar</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>ro.project</name>
    
        <properties>
            <org.springframework.version>3.1.1.RELEASE</org.springframework.version>
            <org.hibernate.version>4.1.0.Final</org.hibernate.version>
        </properties>
        <dependencies>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${org.springframework.version}</version>
            </dependency>
        <build>
            <plugins>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <configuration>
                        <archive>
                            <manifest>
                                <addClasspath>true</addClasspath>
                                <classpathPrefix>lib/</classpathPrefix>
                                <mainClass>ro.project.ProjectServer</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <dependencies>
                        <dependency>
                            <groupId>com.sun</groupId>
                            <artifactId>tools</artifactId>
                            <version>1.7.0_02</version>
                            <scope>system</scope>
                            <systemPath>${java.home}/../lib/tools.jar</systemPath>
                        </dependency>
                    </dependencies>
                    <executions>
                        <execution>
                            <id>ant-magic</id>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <tasks>
                                    <property name="compile_classpath" refid="maven.compile.classpath" />
                                    <property name="runtime_classpath" refid="maven.runtime.classpath" />
                                    <property name="test_classpath" refid="maven.test.classpath" />
                                    <property name="plugin_classpath" refid="maven.plugin.classpath" />
    
                                    <ant antfile="${basedir}/clientExport.xml" target="export-all" />
                                </tasks>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
        <artifactId>project-core</artifactId>
        <url>http://www.project.ro</url>
    </project>
    

    After I run the maven install it is working...

    Maven run configurations:

    maven install deploy jar

    The problem is that my generated .jar it doesn't have the dependencies included.... How can I configure pom.xml to include all my dependencies in .jar format and not unpacked.. because it seems that unpacked are not working correct...

    To be sure that including all jars is ok.. I downloaded and added each library into jar's /lib folder and the jar is running... so.. my only question is: How can I configure pom.xml in order to add all my dependencies in jar format?

    I tried all methods:

    1. assembly:assembly
    2. assembly:single
    3. assembly:single with my descriptor (an assemble.xml file) but it wasn't working
    4. maven copy dependencies plugin but still not working with Eclipse Maven - m2e

    I am out of solutions... can anyone tell me a proper way to add my dependencies in jar? I can't believe that maven is so complex and I can't find an answer to my question everywhere..

    Thank you in advance

  • Edwin Buck
    Edwin Buck about 12 years
    The average jar can contain jars, but the class loader doesn't load jars from within jars, so it's either an uber-jar or a "package" of files with appropriate relative locations.
  • Alex
    Alex about 12 years
    thank you for your answer... I want to deliver a jar that I can execute with java -jar myProject.jar... What you told me here is not adding my packages... how can I do that? thank you a lot... I want also to set my classpath in the jar...
  • Alex
    Alex about 12 years
    now... it is adding my libs in a zip folder(or jar) but my project isn't there.. the result is something like: project-1.0.SNAPSHOT(inside is only a lib folder) and META-INF
  • Raghuram
    Raghuram about 12 years
    @Alex. Set <useProjectArtifact> to true in the assembly descriptor to package the project artifacts as well.
  • Edwin Buck
    Edwin Buck about 12 years
    @Alex Maven has a "one thing" "one project" rule which is part of its design. To make this work, if you haven't done it already, you need two projects. One to build the runnable jar, and a second to build the zip file. The runnable jar has dependencies on the libraries it will need, but it will not include them in the jar file. It will include references to them in the ClassPath entry in the META-INF/MANIFEST.MF file (../lib/lib1.jar and so on). The zip file will also depend on those libs, and the runnable jar. The zip file project will then just build the zip with files in place.
  • Alex
    Alex about 12 years
    aaaaaah, ok.. thank you... I didn't know that.. I thought that there might be a way to generate a single jar that contains everything... :(... I am disappointed by maven :(
  • Edwin Buck
    Edwin Buck about 12 years
    @Alex Every tool has its wrinkles. Maven has excellent dependency management, so it sort of makes sense to have it manage the dependent elements of the zip file (the runnable jar, the other libraries) using its dependency management. However, that does mean you can get a lot more "little" maven projects instead of one big project (like you might do with ant). Your initial request exactly as you requested it "a single jar that contains jars" was not workable anyway, because Java's class loader cannot load Jar files out of Jar files, it can only load class files out of Jar files.