How can I create an executable JAR with dependencies using Maven?
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
and you run it with
mvn clean compile assembly:single
Compile goal should be added before assembly:single or otherwise the code on your own project is not included.
See more details in comments.
Commonly this goal is tied to a build phase to execute automatically. This ensures the JAR is built when executing mvn install
or performing a deployment/release.
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
How to produce an executable jar file with all maven dependencies?
First of all, there are two plugins that you can use to create fat jars: maven-shade-plugin and maven-assembly-plugin.
The main difference between them is that maven-assembly just builds a jar containing all the dependency, while maven-shade also relocate these dependencies internally so that, if another project is depending on your jar, you won't risk having conflicts on dependencies.
If you don't expect yo use this artifact as a dependency of other projects, you can use maven-assembly-plugin for it. Here is an example of how to use it:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<finalName>${project.artifactId}</finalName>
<archive>
<manifest>
<mainClass>myProject.package.main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
If you really need to shade your dependencies, try to modify the manifest config of the plugin with this, at least it should solve the problem that you-re having with identifying the main class:
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>myProject.package.main</Main-Class>
<X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
<X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
</manifestEntries>
</transformer>
Create an executable JAR with all its dependencies and put in the ZIP file using maven assembly
So the problem is that I was running the maven command: mvn package
and this is the problem.
The final pom.xml assembly plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
and the final assembly.xml file:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<files>
<file>
<source>target/${project.artifactId}-${project.version}-jar-with-dependencies.jar</source>
</file>
</files>
<!-- IF YOU NEED TO ADD ALL THE DEPENDENCIES IN ONE FOLDER (lib) -->
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<scope>compile</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<includes>
<include>README*</include>
<include>LICENSE*</include>
<include>NOTICE*</include>
<include>pom.xml</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
<fileSet>
<directory>${project.build.sourceDirectory}/src</directory>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
....
</fileSets>
</assembly>
And never forget to run the command : mvn assembly:assembly -DdescriptorId=jar-with-dependencies package
Make an executable jar using maven java application in netbeans
You need to package the dependency inside the executable jar.
It is a 2 step process:
First, copy all required dependencies into a folder:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Now all the dependencies will be copied in libs folder.
The second step is the creation of an executable and classpath aware jar, with the link to the dependencies copied in the first step:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.oli.ffmpegchunker.MainScreen
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
The overall pom will look like:
<?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.oli</groupId>
<artifactId>FFmpegchunker</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/libs
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.oli.ffmpegchunker.MainScreen
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.github.kokorin.jaffree</groupId>
<artifactId>jaffree</artifactId>
<version>0.9.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.4</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
You can find some simpler approaches for executable jar creation over here using maven assembly plugin and shade plugin.
Building executable jar with maven?
Actually, I think that the answer given in the question you mentioned is just wrong (UPDATE - 20101106: someone fixed it, this answer refers to the version preceding the edit) and this explains, at least partially, why you run into troubles.
It generates two jar files in logmanager/target: logmanager-0.1.0.jar, and logmanager-0.1.0-jar-with-dependencies.jar.
The first one is the JAR of the logmanager module generated during the package
phase by jar:jar
(because the module has a packaging of type jar
). The second one is the assembly generated by assembly:assembly
and should contain the classes from the current module and its dependencies (if you used the descriptor jar-with-dependencies
).
I get an error when I double-click on the first jar:
Could not find the main class: com.gorkwobble.logmanager.LogManager. Program will exit.
If you applied the suggested configuration of the link posted as reference, you configured the jar plugin to produce an executable artifact, something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.gorkwobble.logmanager.LogManager</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
So logmanager-0.1.0.jar
is indeed executable but 1. this is not what you want (because it doesn't have all dependencies) and 2. it doesn't contain com.gorkwobble.logmanager.LogManager
(this is what the error is saying, check the content of the jar).
A slightly different error when I double-click the jar-with-dependencies.jar:
Failed to load Main-Class manifest attribute from: C:\EclipseProjects\logmanager\target\logmanager-0.1.0-jar-with-dependencies.jar
Again, if you configured the assembly plugin as suggested, you have something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
With this setup, logmanager-0.1.0-jar-with-dependencies.jar
contains the classes from the current module and its dependencies but, according to the error, its META-INF/MANIFEST.MF
doesn't contain a Main-Class
entry (its likely not the same MANIFEST.MF as in logmanager-0.1.0.jar). The jar is actually not executable, which again is not what you want.
So, my suggestion would be to remove the configuration
element from the maven-jar-plugin and to configure the maven-assembly-plugin like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<!-- nothing here -->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>org.sample.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Of course, replace org.sample.App
with the class you want to have executed. Little bonus, I've bound assembly:single
to the package
phase so you don't have to run assembly:assembly
anymore. Just run mvn install
and the assembly will be produced during the standard build.
So, please update your pom.xml with the configuration given above and run mvn clean install
. Then, cd into the target
directory and try again:
java -jar logmanager-0.1.0-jar-with-dependencies.jar
If you get an error, please update your question with it and post the content of the META-INF/MANIFEST.MF
file and the relevant part of your pom.xml
(the plugins configuration parts). Also please post the result of:
java -cp logmanager-0.1.0-jar-with-dependencies.jar com.gorkwobble.logmanager.LogManager
to demonstrate it's working fine on the command line (regardless of what eclipse is saying).
EDIT: For Java 6, you need to configure the maven-compiler-plugin. Add this to your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
executable jar with dependencies using maven
As per request in the comments I post this answer:
The jar is built using the maven-jar-plugin, so you can just specify the main-class to it as per the documentation: http://maven.apache.org/shared/maven-archiver/examples/classpath.html
Including dependencies in a jar with Maven
You can do this using the maven-assembly plugin with the "jar-with-dependencies" descriptor. Here's the relevant chunk from one of our pom.xml's that does this:
<build>
<plugins>
<!-- any other plugins -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Executable jar with dependencies and dll dependency using maven
I ended up deleting the dependencySet of the dll from the assembly file and copy the dll dependency with maven-dependency-plugin as follow:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.computer.graphics</groupId>
<artifactId>gluegenrt</artifactId>
<version>1.0</version>
<type>dll</type>
<outputDirectory>${project.build.directory}</outputDirectory>
<destFileName>gluegen-rt.dll</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
The ArrayIndexOutOfBoundsException occurred because I was using jdk 16 instead of jdk 12 to run the jar.
Hope this helps others.
Related Topics
Set Imageview Width and Height Programmatically
Java Refuses to Start - Could Not Reserve Enough Space For Object Heap
What Issues Should Be Considered When Overriding Equals and Hashcode in Java
What Is the Reason Behind "Non-Static Method Cannot Be Referenced from a Static Context"
In Java, How to Determine the Size of an Object
Why Are Static Variables Considered Evil
How to Get the Insert Id in Jdbc
Correct Way to Add External Jars (Lib/*.Jar) to an Intellij Idea Project
How to Create Android Facebook Key Hash
Java Command Not Found on Linux
What Does "Could Not Find or Load Main Class" Mean
Connect to Kafka Running in Docker
Stringbuilder VS String Concatenation in Tostring() in Java
What Is the Java : Operator Called and What Does It Do
How to Handle Infinite Loop Caused by Invalid Input (Inputmismatchexception) Using Scanner