Maven Jar Plugin – How to make an executable jar file

Posted by Marta on February 2, 2023 Viewed 12343 times

Card image cap

In this article you will learn step by step how to create a jar executable file, using the maven jar plugin.

 Let’s say you created a game with java. Your are super excited and want to show your game to your friends. However none of them know programming, so you can’t send them the code so they execute it. 

This is the case for any software you might want to distribute. You need to make your code ready to use. That means compiling the java files, and then package the compiled code and any resources, like images or sounds in a file. This way anyone who want to execute your game, only needs one file. 

What does the maven jar plugin do?

These files are called executable. In java, one of the extension used for executable files is the .jar extension. You could create an executable file manually. You will need to grab all java files, compile them so you get the  class files. Then gather any resources that the program may need, like images or files, and place them in a folder. And lastly add a manifest file specifying the main class, which is the entry point of you program.

You could do all this manually, however copying all files will be tremendously tedious. That’s why maven provides a plugin that help you to automate this repetitive task. 

Maven Quick Reminder

Maven is a build tool that helps you create an artefact, in other words, a file containing your software so it is ready for distribution. The pom.xml file is basically a description of how you will build the artefact.

Plus Maven will manage all third party dependencies that your code needs. To create an artefact, maven follows the following main phases:

maven lifecycle

Step 1) Create sample java code

Let’s start by creating a simple maven project. All this program will do is open a text file, and display the content. As a result, our program will have a .java file and a .txt file, pretty simple.

To create the maven project, run the following maven command:

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart

Then you will need to enter the groupId and artifactId for your project. You can use any name here.

This will generate a project with the following layout:

Now replace the App.java with the following code:

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
  
    public static void main( String[] args ) throws IOException {
        URI path = new File("info.txt").toURI();
        System.out.println(Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8));
  
    }
}

And create a txt file at the root directory called info.txt. Please feel free to change the file name, but if you do so, remember to change the filename at line 11, where the code is accessing the file.

info.txt

hola
hello
salut

Perfect, so we just created a piece of software. Let’s see how we can create an executable. To generate the artefact, you need to run the following maven command from your terminal (and your current directory should be the root of your project):

>> mvn clean package

After running this command, a jar will be created in the target folder.And if I try to execute the jar artifact file, the output will be the following:

Martas-MBP:test-app martarey$ java -jar target/test-app-1.0-SNAPSHOT.jar 
no main manifest attribute, in target/test-app-1.0-SNAPSHOT.jar

There was an error! In the next step, we will see how you can fix this error by adding the maven jar plugin.

Step 2) Adding the maven jar plugin 

Why did you get the above error? The issue here is that when the .jar file was created, no Main class was specified, so java doesn’t know the entry point of our program. To solve this issue, you can use the maven jar plugin. This plugin allows you add configuration describing how to build the jar.

Here is the piece of xml that you should add to your pom.xml file, within the <build> tag:

<pluginManagement>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.0.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>
                            <!--Replace with the class that contains the main function-->
                            com.hellocodeclub.maven.App
                        </mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</pluginManagement>

In case your pom.xml already contains other plugins, just insert the <plugin> tag from above into the plugins section. Now you can create your jar again and execute it, to make sure it works. Execute the following commands from your terminal to regenerate the artefact:

>> mvn clean package
/*  Replace with your jar name   */
>> java -jar target/test-app-1.0-SNAPSHOT.jar

Output:

[hola, hello, salut]

In case you are curious, what is actually included within the jar file, you can check by running the following command:

>> jar tf target/test-app-1.0-SNAPSHOT.jar

Step 3) Adding dependencies to your jar

What if your program is using dependencies? The piece of code you created, it’s only using java, however in a real scenario, you will use third party dependencies to write your code. Let’s see how to include this dependencies into your executable.

First let’s modify our previous program to use a third party dependency. In this case I will add the apache commons io library. The code will actually do exactly the same, but using a dependency. To include this dependency you need to do the following. Firstly, add the dependency to your pom.xml file in the dependencies section:

<dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.5</version>
</dependency>

And then modify the App class as follows:

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class App 
{
    public static void main( String[] args ) throws IOException {

        File file = new File("info.txt");
        List<String> lines = FileUtils.readLines(file, "UTF-8");
        System.out.println(lines);
    }
}

So we just included the dependency. So if you create a jar file using mvn clean package and execute the file using java -jar target/<replace-with-your-file-name>.jar you will get following error:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/FileUtils
        at com.hellocodeclub.maven.App.main(App.java:15)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.io.FileUtils
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 1 more

This basically means the code was expecting to find a FileUtils.class file, however this class, which is part of the commons.io dependency wasn’t included in the executable jar. To remediate this problem you will need to add some extra configuration to your pom.xml file.

First, you will need to add the maven-dependency-plugin. This plugin will download the dependencies(the jar files) and copy them in a folder named dependency, located next to your jar file.

Also you should include the <classpathPrefix> property in the maven-jar-plugin, which will indicates to java where the dependency code can be found.

See below what you will need to add to your pom.xml file to put this into action. Add the xml below inside the <pluginManagement> tag:

 <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-dependency-plugin</artifactId>
              <version>3.0.1</version>
              <executions>
                  <execution>
                      <id>copy-dependencies</id>
                      <phase>package</phase>
                      <goals>
                          <goal>copy-dependencies</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-jar-plugin</artifactId>
              <version>3.0.2</version>
              <configuration>
                  <archive>
                      <manifest>
                          <addClasspath>true</addClasspath>
                          <classpathPrefix>dependency/</classpathPrefix>
                          <mainClass>com.hellocodeclub.maven.App</mainClass>
                      </manifest>
                  </archive>
              </configuration>
          </plugin>
      </plugins>

Once you modified the pom.xml file, execute the following command from your terminal (at the project root) to recreate the executable:

>> mvn clean dependency:copy-dependencies package
>> java -jar target/test-app-1.0-SNAPSHOT.jar  

And the output should be:

[hola, hello, salut]

And a small note, in case you would like to move your java to another folder, remember that will need to move the dependency folder as well. This is important because otherwise, your jar won’t be able to find the dependencies.

Conclusion

In conclusion, you have learnt how to can create a jar executable file using the maven jar plugin and the exact configuration you should use. Plus, we have also seen how you can include dependencies to your executable jar file. I hope you enjoyed the tutorial and thank you so much for reading and supporting this blog! 🙂

More Interesting Articles

Project-Based Programming Introduction

Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications

100% Recommended book for Java Beginners

Unique lay-out and teaching programming style helping new concepts stick in your memory

90 Specific Ways to Write Better Python

Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples

Grow Your Java skills as a developer

Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.

Write Code as a Professional Developer

Excellent read for anyone who already know how to program and want to learn Best Practices

Every Developer should read this

Perfect book for anyone transitioning into the mid/mid-senior developer level

Great preparation for interviews

Great book and probably the best way to practice for interview. Some really good information on how to perform an interview. Code Example in Java