eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

eBook – Maven – NPI (cat=Maven)
announcement - icon

Get up to speed with the core of Maven quickly, and then go beyond the foundations into the more powerful functionality of the build tool, such as profiles, scopes, multi-module projects and quite a bit more:

>> Download the core Maven eBook

1. Overview

In this quick tutorial, we’ll focus on packaging a Maven project into an executable Jar file.

When creating a jar file, we usually want to run it easily, without using the IDE. To that end, we’ll discuss the configuration and pros/cons of using each of these approaches for creating the executable.

Further reading:

Apache Maven Tutorial

A quick and practical guide to building and managing Java projects using Apache Maven.

Where Is the Maven Local Repository?

Quick tutorial showing you where Maven stores its local repo and how to change that.

Spring with Maven BOM

Learn how to use a BOM, Bill of Materials, in your Spring Maven project.

2. Configuration

We don’t need any additional dependencies to create an executable jar. We just need to create a Maven Java project and have at least one class with the main(…) method.

In our example, we created a Java class named ExecutableMavenJar.

We also need to make sure that our pom.xml contains these elements:

<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>core-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>jar</packaging>

The most important aspect here is the type — to create an executable jar, double-check the configuration uses a jar type.

Now we can start using the various solutions.

2.1. Manual Configuration

Let’s start with a manual approach with the help of the maven-dependency-plugin.

We’ll begin by copying all required dependencies into the folder that we’ll specify:

<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>

There are two important aspects to notice.

First, we specify the goal copy-dependencies, which tells Maven to copy these dependencies into the specified outputDirectory. In our case, we’ll create a folder named libs inside the project build directory (which is usually the target folder).

Second, we are going to create 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.baeldung.executable.ExecutableMavenJar
                </mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

The most important part of this is the manifest configuration. We add a classpath, with all dependencies (folder libs/), and provide the information about the main class.

Please note that we need to provide a fully qualified name of the class, which means it will include the package name.

The advantages and disadvantages of this approach are:

  • pros – transparent process, where we can specify each step
  • cons – manual; dependencies are out of the final jar, which means that our executable jar will only run if the libs folder will be accessible and visible for a jar

2.2. Apache Maven Assembly Plugin

The Apache Maven Assembly Plugin allows users to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single, runnable package.

The main goal in the assembly plugin is the single goal, which is used to create all assemblies (all other goals are deprecated and will be removed in a future release).

Let’s take a look at the configuration in pom.xml:

<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>
                        com.baeldung.executable.ExecutableMavenJar
                    </mainClass>
                </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </execution>
    </executions>
</plugin>

Similarly to the manual approach, we need to provide the information about the main class. The difference is that the Maven Assembly Plugin will automatically copy all required dependencies into a jar file.

In the descriptorRefs part of the configuration code, we provided the name that will be added to the project name.

Output in our example will be named core-java-jar-with-dependencies.jar.

  • pros – dependencies inside the jar file, one file only
  • cons – basic control of packaging our artifact, for example, there is no class relocation support

2.3. Apache Maven Shade Plugin

Apache Maven Shade Plugin provides the capability to package the artifact in an uber-jar, which consists of all dependencies required to run the project. Moreover, it supports shading — i.e. renaming — the packages of some of the dependencies.

Let’s take a look at the configuration:

<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>com.baeldung.executable.ExecutableMavenJar</mainClass>
                </transformer>
            </transformers>
        </configuration>
        </execution>
    </executions>
</plugin>

There are three main parts to this configuration.

First, <shadedArtifactAttached> marks all dependencies to be packaged into the jar.

Second, we need to specify the transformer implementation; we used the standard one in our example.

Finally, we need to specify the main class of our application.

The output file will be named core-java-0.1.0-SNAPSHOT-shaded.jar, where core-java is our project name followed by snapshot version and plugin name.

  • pros – dependencies inside the jar file, advanced control of packaging our artifact, with shading and class relocation
  • cons – complex configuration (especially if we want to use advanced features)

2.4. One Jar Maven Plugin

Another option to create an executable jar is the One Jar project.

This provides a custom class loader that knows how to load classes and resources from jars inside an archive, instead of from jars in the filesystem.

Let’s take a look at the configuration:

<plugin>
    <groupId>com.jolira</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <executions>
        <execution>
            <configuration>
                <mainClass>org.baeldung.executable.
                  ExecutableMavenJar</mainClass>
                <attachToBuild>true</attachToBuild>
                <filename>
                  ${project.build.finalName}.${project.packaging}
                </filename>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

As shown in the configuration, we need to specify the main class and attach all dependencies to the build, by using attachToBuild = true.

Also, we should provide the output filename. Moreover, the goal for Maven is one-jar. Please note that One Jar is a commercial solution that will make dependency jars not expanded into the filesystem at runtime.

  • pros – clean delegation model, allows classes to be at the top level of the One Jar, supports external jars, and can support Native libraries
  • cons – not actively supported since 2012

2.5. Spring Boot Maven Plugin

Finally, the last solution we’ll look at is the Spring Boot Maven Plugin.

This allows for packaging executable jar or war archives and run an application “in place.”

To use it, we need to use at least Maven version 3.2. The detailed description is available here.

Let’s have a look at the config:

<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>
                  com.baeldung.executable.ExecutableMavenJar
                </mainClass>
            </configuration>
        </execution>
    </executions>
</plugin>

There are two differences between the Spring plugin and the others: The goal of the execution is called repackage, and the classifier is named spring-boot.

Note that we don’t need to have a Spring Boot application in order to use this plugin.

  • pros – dependencies inside a jar file, we can run it in every accessible location, advanced control of packaging our artifact, with excluding dependencies from the jar file, packaging of war files, and more
  • cons – adds potentially unnecessary Spring and Spring Boot-related classes

2.6. Web Application With Executable Tomcat

In the last part, we want to cover a standalone web application that is packed inside a jar file.

In order to do that, we need to use different plugin, designed for creating executable jar files:

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.0</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <path>/</path>
                <enableNaming>false</enableNaming>
                <finalName>webapp.jar</finalName>
                <charset>utf-8</charset>
            </configuration>
        </execution>
    </executions>
</plugin>

The goal is set as exec-war-only, path to our server is specified inside the configuration tag, with additional properties, like finalName, charset, and more.

To build a jar, we run mvn package, which will result in creating webapp.jar in our target directory.

To run the application, we just write java -jar target/webapp.jar in our console and try to test it by specifying the localhost:8080/ in a browser.

  • pros – having one file, easy to deploy and run
  • cons – a size of the file is much larger, due to packing Tomcat embedded distribution inside a war file

Note that this is the latest version of this plugin, which supports Tomcat7 server. To avoid errors, we can check that our dependency for Servlets has scope set as provided, otherwise, there will be a conflict at the runtime of executable jar:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <scope>provided</scope>
</dependency>

2.7. Create Executable Using Launch4j in Maven

To integrate Launch4j with Maven, we’ll use the launch4j-maven-plugin. This plugin allows us to configure and generate an executable .exe file directly from our Maven build process.

Let’s add the launch4j-maven-plugin to our pom.xml:

<plugin>
    <groupId>com.akathist.maven.plugins.launch4j</groupId>
    <artifactId>launch4j-maven-plugin</artifactId>
    <version>2.5.3</version>
    <executions>
        <execution>
            <id>l4j-clui</id>
            <phase>package</phase>
            <goals>
                <goal>launch4j</goal>
            </goals>
            <configuration>
                <headerType>gui</headerType>
                <outfile>${project.build.directory}/${project.build.finalName}.exe</outfile>
                <jar>${project.build.directory}/${project.build.finalName}.jar</jar>
                <errTitle>App Error</errTitle>
                <classPath>
                    <mainClass>com.baeldung.executable.ExecutableMavenJar</mainClass>
                </classPath>
            </configuration>
        </execution>
    </executions>
</plugin>

The outfile specifies the name and location of the output .exe file, typically placed in the target directory with the same name as the final JAR.

The jar element points to the JAR file that will be wrapped into the executable, ensuring the correct application is bundled.

To generate the .exe file, we run the Maven package command:

mvn clean package

This creates the executable .exe file in the target directory, alongside the JAR file. The .exe file can be distributed to users, who can run it without needing to use the command line.

By using the launch4j-maven-plugin, we can easily create a Windows executable from a JAR file, simplifying the distribution and execution of Java applications for Windows users.

3. Create Multiple Runnable Jars

Creating multiple runnable JAR files from a single Maven project is useful when we want to package different functionalities or applications, each with its own main() method, into separate JARs.

First of all, we need to have multiple entry points (main classes) in our project. For example:

// Main1.java
public class Main1 {
    public static void main(String[] args) {
        System.out.println("Hello from Main1!");
    }
}

// Main2.java
public class Main2 {
    public static void main(String[] args) {
        System.out.println("Hello from Main2!");
    }
}

3.1. Using maven-assembly-plugin

To package each main class into its own runnable JAR, we can use the maven-assembly-plugin. Below is an example configuration using the maven-assembly-plugin:

<profile>
    <id>multiple-jar-profile</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <id>create-jar-for-main1</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>com.baeldung.multiplejar.Main1</mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                            <finalName>main1-runnable</finalName>
                            <appendAssemblyId>false</appendAssemblyId>
                        </configuration>
                    </execution>
                    <execution>
                        <id>create-jar-for-main2</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>com.baeldung.multiplejar.Main2</mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                            <finalName>main2-runnable</finalName>
                            <appendAssemblyId>false</appendAssemblyId>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Next, we can run the Maven package goal to build the project:

mvn clean package -Pmultiple-jar-profile

This will generate two runnable JAR files in the target/ directory:

main1-runnable.jar
main2-runnable.jar

We can test each JAR to ensure it works as expected by running the -jar command:

java -jar target/main1-runnable.jar
# Output: Hello from Main1!

java -jar target/main2-runnable.jar
# Output: Hello from Main2!

3.2. Using maven-shade-plugin

Alternatively, we can use the maven-shade-plugin to achieve the same result. Let’s update our pom.xml to use maven-shade-plugin:

<profile>
    <id>multiple-jar-profile2</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>${maven-shade-plugin.version}</version>
                <executions>
                    <execution>
                        <id>shade-main1</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <shadedClassifierName>main1</shadedClassifierName>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.baeldung.multiplejar.Main1</mainClass>
                                </transformer>
                            </transformers>
                            <finalName>main1-runnable</finalName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>shade-main2</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <shadedClassifierName>main2</shadedClassifierName>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.baeldung.multiplejar.Main2</mainClass>
                                </transformer>
                            </transformers>
                            <finalName>main2-runnable</finalName>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

By using the maven-assembly-plugin or maven-shade-plugin, we can easily create multiple runnable JARs from a single Maven project. This approach is ideal for projects with multiple main classes, allowing us to package and distribute each application separately.

4. Conclusion

In this article, we described many ways of creating an executable jar with various Maven plugins.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.

How to test? In order to compile the project into an executable jar, please run Maven with the mvn clean package command.

This article hopefully provided some more insights and will help you find your preferred approach depending on your needs.

One quick final note: We want to make sure the licenses of the jars we’re bundling don’t prohibit this kind of operation. That generally won’t be the case, but it’s worth considering.

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)