86

I'm relatively new to the Maven mantra, but I'm trying to build a command-line runnable jar with Maven. I've setup my dependencies, but when I run mvn install and attempt to run the jar, two things happen. First, no main class is found, which is correctable. When I've corrected this, I get errors on run stating that classes cannot be found.

Maven is not packaging my dependency libraries inside of the jar, so I am unable to run the jar as a stand-alone application. How do I correct this?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
  • Maybe this one http://stackoverflow.com/questions/1832853/is-it-possible-to-create-an-uber-jar-containing-the-project-classes-and-the-pro, or this one http://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven (but the accepted answer is wrong), or this one http://stackoverflow.com/questions/1814526/problem-building-executable-jar-with-maven. Actually, this seems to be one of the most frequent question on maven... – Pascal Thivent Jan 07 '10 at 18:00
  • 1
    The other answers aren't as clean, and uber jar (ueber spelled incorrectly), does not mention executability. Furthermore, the other topics are littered with irrelevant material, such as source level etc. – Stefan Kendall Jan 07 '10 at 18:21
  • possible duplicate of [Is it possible to package all the jar dependencies in one big jar?](http://stackoverflow.com/questions/1059851/is-it-possible-to-package-all-the-jar-dependencies-in-one-big-jar) – ataylor Dec 08 '11 at 16:20
  • I see many of the answers are ~10 years old, so I would be interested to see if there is anything different now. – Aaron Kurtzhals Sep 23 '22 at 14:44

6 Answers6

114

The easiest way to do this would be to create an assembly using the maven-assembly-plugin and the predefined jar-with-dependencies descriptor. You'll also need to generate a manifest with a main-class entry for this uber jar. The snippet below shows how to configure the assembly plugin to do so:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>
  </plugins>
</build>

Then, to generate the assembly, just run:

mvn assembly:assembly

If you want to generate the assembly as part of your build, simply bind the assembly:single mojo to the package phase:

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
      </configuration>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

And simply run:

mvn package
Adrian Petrescu
  • 16,629
  • 6
  • 56
  • 82
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 1
    The maven-shade-plugin also works similarly and is dedicated to this purpose. – Dominic Mitchell Jan 07 '10 at 20:46
  • 4
    This does not work for spring, and other libraries that expect multiple resources with the same name on the class path. In the case of spring, META-INF\spring.schemas is included in several jars (beans, jdbc, etc) and is used to configure XML namespace support for the XML parser. If you try 'jar-with-dependencies', pasing application-context.xml will fail at runtime with something like "org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'beans'." – David Roussel Mar 04 '10 at 10:37
  • @David Maven won't solve a Java "limitation". Just package your application cleanly (i.e. not in a uberjar) in that case. – Pascal Thivent Mar 04 '10 at 15:55
  • This works with Spring configuration with no issues. My main class loads all other classes with Classpath Application context and this solution works perfectly. – vsingh Dec 20 '10 at 18:25
  • 2
    The `assembly:assembly` goal is [deprecated](http://maven.apache.org/plugins/maven-assembly-plugin/) – Jared Beck Nov 04 '13 at 00:11
  • Is it possible to have resulting jar to have a "normal" name? – Daniil Shevelev Feb 11 '14 at 16:09
  • To answer my own comment: using "shade" plugin with "transformers" property works. – Daniil Shevelev Feb 11 '14 at 16:58
  • to solve the issue in comment no. 2 I used Shade as in this link http://stackoverflow.com/questions/5586515/idea-to-avoid-that-spring-handlers-spring-schemas-get-overwritten-when-merging-m – Bassem Reda Zohdy Mar 04 '14 at 18:42
26

Maven is not packaging your dependencies inside your jar file, because you don't usually do this with Java programs.

Instead you deliver the dependencies together with your jar file and mention them in the Class-Path header of the Manifest.

To go this route, you'll need to enable the addClasspath property (documented here) for the maven-jar-plugin.

If you really want to include all your dependencies in your jar file, then you can use the Maven Assembly plugin to create a jar-with-dependencies.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 5
    +1 I've had a hard time finding information on how java programs are *typically intended* to be built and distributed, especially with Maven. – Ed Brannin Feb 06 '12 at 17:30
8

This is what I would do for small projects. Most of the time you don't want one huge jar.

to build: mvn clean dependency:copy-dependencies package

to execute (in target dir): java -cp myjar.jar:./dependency/* com.something.MyClass

user2409824
  • 81
  • 1
  • 1
6

I Agree with Joachim Sauer,

Instead of using jar-with-dependency you should configure the jar plugin like that in your pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <index>true</index>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>[mainClassFullName]</mainClass>
            </manifest>
            <manifestEntries>
                <mode>development</mode>
                <url>${project.url}</url>
                <key>value</key>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

And use this assembly configuration to add the jar dependencies to you assembly:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
  <id>zip-with-jars</id>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySets>
    <dependencySet>
    <outputDirectory>/</outputDirectory>
    <useProjectArtifact>true</useProjectArtifact>
    <unpack>false</unpack>
    <scope>runtime</scope>
    </dependencySet>
</dependencySets>
  </dependencySets>
</assembly>
formixian
  • 1,549
  • 16
  • 25
2

Just add the below code in pom.xml and Run as: maven:install . The jar will be created in target folder of eclipse which can be used as "java -jar Hello.jar" . but make sure that name of main class is given com.abc.HelloWorld.java

<build>
<plugins>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-shade-plugin</artifactid>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalname>HelloW</finalname>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestentries>
<main-class>com.abc.HelloWorld.java</main-class>
<build-number>1</build-number>
</manifestentries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>

</build>
likeGreen
  • 1,001
  • 1
  • 20
  • 40
0

I have a spring boot application, and the jar created by maven package can be run without setting up additional plugins.

Inside my pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.12</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

https://spring.io/projects/spring-boot

Aaron Kurtzhals
  • 2,036
  • 3
  • 17
  • 21