Posted by Marta on February 2, 2023 Viewed 12343 times
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.
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 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:
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.
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
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.
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! 🙂
Steady pace book with lots of worked examples. Starting with the basics, and moving to projects, data visualisation, and web applications
Unique lay-out and teaching programming style helping new concepts stick in your memory
Great guide for those who want to improve their skills when writing python code. Easy to understand. Many practical examples
Perfect Boook for anyone who has an alright knowledge of Java and wants to take it to the next level.
Excellent read for anyone who already know how to program and want to learn Best Practices
Perfect book for anyone transitioning into the mid/mid-senior developer level
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