I want to package my project in a single executable JAR for distribution.
How can I make a Maven project package all dependency JARs into my output JAR?
<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>
Answered 2023-09-20 20:23:31
mvn clean compile assembly:single
. - anyone <appendAssemblyId>false</appendAssemblyId>
into the configuration
to avoid the annoying "-jar-with-dependencies" suffix in the name - anyone maven-compiler-plugin
. Tests? maven-surefire-plugin
. These two, including the assembly, are official maven plugins, so they might as well be considered as part of maven (esp. cause, at least now, all three of them are in your effective POM by default). - anyone You can use the dependency-plugin to generate all dependencies in a separate directory before the package phase and then include that in the classpath of the manifest:
<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}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>theMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Alternatively, use ${project.build.directory}/classes/lib
as OutputDirectory to integrate all JAR files into the main JAR file, but then you will need to add custom classloading code to load the JAR files.
Answered 2023-09-20 20:23:31
See executable-jar-with-maven-example (GitHub)
Those pros and cons are provided by Stephan.
<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}/${project.build.finalName}.lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
<mainClass>${fully.qualified.main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
At this point the JAR file is actually executable with external classpath elements.
java -jar target/${project.build.finalName}.jar
The JAR file is only executable with the sibling ...lib/
directory. We need to make archives to deploy with the directory and its content.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>antrun-archive</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property name="final.name" value="${project.build.directory}/${project.build.finalName}"/>
<property name="archive.includes" value="${project.build.finalName}.${project.packaging} ${project.build.finalName}.lib/*"/>
<property name="tar.destfile" value="${final.name}.tar"/>
<zip basedir="${project.build.directory}" destfile="${final.name}.zip" includes="${archive.includes}" />
<tar basedir="${project.build.directory}" destfile="${tar.destfile}" includes="${archive.includes}" />
<gzip src="${tar.destfile}" destfile="${tar.destfile}.gz" />
<bzip2 src="${tar.destfile}" destfile="${tar.destfile}.bz2" />
</target>
</configuration>
</execution>
</executions>
</plugin>
Now you have target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
which each contains the jar
and lib/*
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>${fully.qualified.main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
You have target/${project.bulid.finalName}-jar-with-dependencies.jar
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${fully.qualified.main.class}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
You have target/${project.build.finalName}-shaded.jar
.
<plugin>
<!--groupId>org.dstovall</groupId--> <!-- not available on the central -->
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<executions>
<execution>
<configuration>
<mainClass>${fully.qualified.main.class}</mainClass>
<attachToBuild>true</attachToBuild>
<!-- https://code.google.com/p/onejar-maven-plugin/issues/detail?id=8 -->
<!-- classifier>onejar</classifier -->
<filename>${project.build.finalName}-onejar.${project.packaging}</filename>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>${fully.qualified.main.class}</mainClass>
</configuration>
</execution>
</executions>
</plugin>
You have target/${project.bulid.finalName}-spring-boot.jar
.
<plugin>
<groupId>io.quarkus.platform</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<skipOriginalJarRename>true</skipOriginalJarRename> <!-- keep the original jar without .origin -->
<properties>
<quarkus.native.container-build>false</quarkus.native.container-build>
<quarkus.package.type>uber-jar</quarkus.package.type>
<quarkus.package.main-class>${mainClass}</quarkus.package.main-class>
<quarkus.package.output-directory>${project.build.directory}</quarkus.package.output-directory>
<quarkus.package.runner-suffix>-quarkus</quarkus.package.runner-suffix>
</properties>
</configuration>
<executions>
<execution>
<id>uber-jar</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
You have target/${project.bulid.finalName}-quarkus.jar.
Answered 2023-09-20 20:23:31
quarkus-maven-plugin
added. Your move? stackoverflow.com/users/363573/stephan - anyone Taking IAdapter's answer and reformatting it, we have:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Next, I would recommend making this a natural part of your build, rather than something to call explicitly. To make this a integral part of your build, add this plugin to your pom.xml
and bind it to the package
lifecycle event. However, a gotcha is that you need to call the assembly:single
goal if putting this in your pom.xml, while you would call 'assembly:assembly' if executing it manually from the command line.
<project>
[...]
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
[...]
</plugins>
[...]
</build>
</project>
Answered 2023-09-20 20:23:31
Use the maven-shade-plugin to package all dependencies into one über-JAR file. It can also be used to build an executable JAR file by specifying the main class. After trying to use maven-assembly and maven-jar, I found that this plugin best suited my needs.
I found this plugin particularly useful as it merges the content of specific files instead of overwriting them. This is needed when there are resource files that are have the same name across the JAR files and the plugin tries to package all the resource files.
See the example below:
<plugins>
<!-- This plugin provides the capability to package
the artifact in an über-JAR file, including
its dependencies and to shade - i.e. rename -
the packages of some of the dependencies. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<!-- Signed JAR files-->
<excludes>
<exclude>bouncycastle:bcprov-jdk15</exclude>
</excludes>
</artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- Main class -->
<mainClass>com.main.MyMainClass</mainClass>
</transformer>
<!-- Use resource transformers to prevent file overwrites -->
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>properties.properties</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>applicationContext.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Answered 2023-09-20 20:23:31
You can use the maven-shade plugin to build an über JAR file like below:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Answered 2023-09-20 20:23:31
I have long used the Maven assembly plugin, but I could not find a solution to the problem with "already added, skipping"
. Now, I'm using another plugin - onejar-maven-plugin. An example is below (mvn package
builds the JAR file):
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.3.0</version>
<executions>
<execution>
<configuration>
<mainClass>com.company.MainClass</mainClass>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
You need to add a repository for that plugin:
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>
Answered 2023-09-20 20:23:31
You can add the following to your pom.xml file:
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mycompany.package.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.mycompany.package.MainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Afterwards you have to switch via the console to the directory, where the pom.xml file is located. Then you have to execute mvn assembly:single and then your executable JAR file with dependencies will be hopefully build. You can check it when switching to the output (target) directory with cd ./target and starting your JAR with a command similar to java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar.
I tested this with Apache Maven 3.0.3.
Answered 2023-09-20 20:23:31
I went through every one of these responses looking to make a fat executable JAR file containing all dependencies and none of them worked right. The answer is the shade plugin, it’s very easy and straightforward.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>path.to.MainClass</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Be aware that your dependencies need to have a scope of compile or runtime for this to work properly.
Answered 2023-09-20 20:23:31
You can use maven-dependency-plugin, but the question was how to create an executable JAR file. To do that requires the following alteration to Matthew Franglen's response (btw, using the dependency plugin takes longer to build when starting from a clean target):
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>${basedir}/target/dependency</directory>
</resource>
</resources>
</build>
Answered 2023-09-20 20:23:31
Another option if you really want to repackage the other JARs contents inside your single resultant JAR is the Maven Assembly plugin. It unpacks and then repacks everything into a directory via <unpack>true</unpack>
. Then you'd have a second pass that built it into one massive JAR.
Another option is the OneJar plugin. This performs the above repackaging actions all in one step.
Answered 2023-09-20 20:23:31
You could combine the maven-shade-plugin
and maven-jar-plugin
.
maven-shade-plugin
packs your classes and all dependencies in a single JAR file.maven-jar-plugin
to specify the main class of your executable JAR file (see Set Up The Classpath, chapter "Make The Jar Executable").Example POM configuration for maven-jar-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.example.MyMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Finally create the executable JAR file by invoking:
mvn clean package shade:shade
Answered 2023-09-20 20:23:31
It will work like:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
Unpacking has to be in the generate-resources phase or it will not be included as resources.
Answered 2023-09-20 20:23:31
Plugin execution not covered by lifecycle configuration: org.apache.maven.plugins:maven-dependency-plugin:2.8:unpack-dependencies (execution: unpack-dependencies, phase: generate-resources)
- anyone Ken Liu has it right in my opinion. The Maven dependency plugin allows you to expand all the dependencies, which you can then treat as resources. This allows you to include them in the main artifact. The use of the assembly plugin creates a secondary artifact which can be difficult to modify - in my case I wanted to add custom manifest entries. My POM file ended up as:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
...
<resources>
<resource>
<directory>${basedir}/target/dependency</directory>
<targetPath>/</targetPath>
</resource>
</resources>
</build>
...
</project>
Answered 2023-09-20 20:23:31
To resolve this issue, we will use the Maven Assembly plugin that will create the JAR file together with its dependency JAR files into a single executable JAR file. Just add the below plugin configuration in your pom.xml file.
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.your.package.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
After doing this, don’t forget to run the Maven tool with this command:
mvn clean compile assembly:single
Maven - Creating a JAR file together with its dependency JAR files into a single executable JAR file
Answered 2023-09-20 20:23:31
What is the problem with locating shared assembly files with maven-assembly-plugin-2.2.1?
Try using the descriptorId configuration parameter instead of descriptors/descriptor or descriptorRefs/descriptorRef parameters.
Neither of them do what you need: look for the file on classpath. Of course you need adding the package where the shared assembly resides on the maven-assembly-plugin's classpath (see below). If you're using Maven 2.x (not Maven 3.x), you may need adding this dependency in top-most parent pom.xml in the pluginManagement section.
See this for more details.
Class: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader
Example:
<!-- Use the assembly plugin to create a zip file of all our dependencies. -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorId>assembly-zip-for-wid</descriptorId>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>cz.ness.ct.ip.assemblies</groupId>
<artifactId>TEST_SharedAssemblyDescriptor</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
Answered 2023-09-20 20:23:31
I compared the tree plugins mentioned in this post. I generated two JAR files and a directory with all the JAR files. I compared the results and definitely the maven-shade-plugin is the best.
My challenge was that I have multiple Spring resources that needed to be merged, as well as jax-rs, and JDBC services. They were all merged properly by the shade plugin in comparison with the maven-assembly-plugin. In which case Spring will fail unless you copy them to your own resources folder and merge them manually one time.
Both plugins output the correct dependency tree. I had multiple scopes like test, provide, compile, etc. The test and provided were skipped by both plugins. They both produced the same manifest, but I was able to consolidate licenses with the shade plugin using their transformer. With the maven-dependency-plugin of course you don't have those problems, because the JAR files are not extracted. But like some other have pointed out, you need to carry one extra file(s) to work properly.
Here is a snip of the pom.xml file:
<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}/lib</outputDirectory>
<includeScope>compile</includeScope>
<excludeTransitive>true</excludeTransitive>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.factories</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.tooling</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
Answered 2023-09-20 20:23:31
For anyone looking for options to exclude specific dependencies from the über JAR file, this is a solution that worked for me:
<project...>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>1.6.1</version>
<scope>provided</scope> <!-- <============= -->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>...</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
It's not a configuration of the mvn-assembly-plugin, but a property of the dependency.
Answered 2023-09-20 20:23:31
It may not be a good idea to embed all the dependencies in the project's JAR file itself.
I see the point (ease of deployment / usage), but it depends of the use case of your project (and there may be alternatives (see below)).
If you use it fully standalone, why not?
But if you use your project in other contexts (like in a web application, or dropped in a folder where other JARs are sitting), you may have JAR duplicates in your classpath (the ones in the folder, the one in the JAR files). Maybe not a bid deal, but I usually avoid this.
A good alternative:
Like this, with in the end just a manifest and a "special dynamic classloader main", you can start your project with:
java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
Answered 2023-09-20 20:23:31
Something that has worked for me was:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>SimpleKeyLogger</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
I had an extraordinary case, because my dependency was system one:
<dependency>
..
<scope>system</scope>
<systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>
I have changed the code provided by user189057 with changes:
Answered 2023-09-20 20:23:31
This is the best way I found:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.myDomain.etc.MainClassName</mainClass>
<classpathPrefix>dependency-jars/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/dependency-jars/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
With this configuration, all dependencies will be located in /dependency-jars
. My application has no Main
class, just context ones, but one of my dependencies do have a Main
class (com.myDomain.etc.MainClassName
) that starts the JMX server, and receives a start
or a stop
parameter. So with this I was able to start my application like this:
java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
Answered 2023-09-20 20:23:31
There are millions of answers already. I wanted to add you don't need <mainClass>
if you don't need to add entryPoint to your application. For example, APIs may not have necessarily have a main
method.
<build>
<finalName>log-enrichment</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
mvn clean compile assembly:single
ll target/
total 35100
drwxrwx--- 1 root vboxsf 4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf 4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf 0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf 0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf 0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf 0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf 0 Sep 29 16:08 maven-status/
Answered 2023-09-20 20:23:31
I wanted to migrate my Spring application (using Apereo Foundation's CAS client) to Spring Boot 1.5. I ran into many problems, like:
no main manifest attribute, in target/cas-client-web.jar
I tried to make one unique JAR file with all dependencies. After searching on the Internet, I was able to do it with these lines:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${start-class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
start-class is my main class:
<properties>
<java.version>1.8</java.version>
<start-class>com.test.Application</start-class>
</properties>
And my Application is:
package com.test;
import java.util.Arrays;
import com.test.TestProperties;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableAutoConfiguration
@EnableConfigurationProperties({TestProperties.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
Answered 2023-09-20 20:23:31
To create an executable JAR from the command line itself, just run the below command from the project path:
mvn assembly:assembly
Answered 2023-09-20 20:23:31
pom.xml
otherwise you get Error reading assemblies: No assembly descriptors found.
. That's what happens for me anyway. - anyone This could also be an option. You will be able to build your JAR file.
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>WordListDriver</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Answered 2023-09-20 20:23:31
I tried the most upvoted answer here and was able to get the JAR file runnable. But the program didn't run correctly. I do not know what the reason was. When I try to run from Eclipse, I get a different result, but when I run the JAR file from command line I get a different result (it crashes with a program-specific runtime error).
I had a similar requirement as the OP just that I had too many (Maven) dependencies for my project. Fortunately, the only solution that worked for me was that using Eclipse. It is very simple and very straightforward. This is not a solution for the OP, but it is a solution for someone who has a similar requirement, but with many Maven dependencies,
Just right-click on your project folder (in Eclipse) and select Export
Then select Java → Runnable JAR
You will be asked to choose the location of the JAR file
Finally, select the class that has the Main method that you want to run and choose *Package dependencies with the JAR file and click Finish
Answered 2023-09-20 20:23:31
Add to file pom.xml:
<dependency>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
</dependency>
And
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
That’s it. Next, the mvn package will also create one fat JAR additionally, including all dependency JAR files.
Answered 2023-09-20 20:23:31
The maven-assembly-plugin worked great for me.
I spent hours with the maven-dependency-plugin and couldn't make it work. The main reason was that I had to define the artifact items explicitly in the configuration section which should be included as it is described in the documentation.
There is an example there for the cases when you want to use it like: mvn dependency:copy
, where there are not included any artifactItems, but it doesn't work.
Answered 2023-09-20 20:23:31
I tried multiple solutions, but this is the one that worked perfectly in the scenario where we wanted to create a non-executable fat JAR file with all internal dependencies for external systems having no previous relevance. A production scenario was tested.
Include this in the pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
The command to run to build the fat JAR file:
mvn assembly:assembly
Answered 2023-09-20 20:23:31
This blog post shows another approach with combining the maven-jar and maven-assembly plugins. With the assembly configuration XML file from the blog post it can also be controlled if dependencies will be expanded or just be collected in a folder and referenced by a classpath entry in the manifest:
The ideal solution is to include the jars in a lib folder and the manifest.mf file of the main jar include all the jars in classpath.
And exactly that one is described here: Executable JAR file with dependent JAR files using Maven
Answered 2023-09-20 20:23:31