How to manually create the jar file for running your Java application
Advances in software engineering had shortened the time needed to build an application from scratch. For instance with Spring Boot, I can easily build my own web API backed by a web server of my choice into a single jar file. By running that jar file, I can start a process that responds to HTTP requests directed at my customized endpoints.
However, not knowing how that jar file is formed and read by the Java Virtual Machine can cloud our understanding of application development with Java. To help understand Java application development better, I described how to manually create a jar file for running a Java application.
Defining a sample scenario
As the topic of this post is to document the process of manually preparing an executable jar file, I shall define a simple scenario for my Java application.
Let's suppose that I want to build a Java application that downloads Techcoil's robots.txt and saves it in the same directory where my Java application resides in.
To fulfil this requirement, I refer to my previous post on how to send HTTP GET request with Java without using any external libraries to derive the following Java source file:
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.Scanner; public class TechcoilRobotTxtDownloader { public static void main(String[] args) { ByteArrayOutputStream responseBodyBaos = null; Scanner httpResponseBodyScanner = null; try { // Define server endpoint URL robotsUrl = new URL("http://www.techcoil.com/robots.txt"); HttpURLConnection urlConnection = (HttpURLConnection) robotsUrl.openConnection(); httpResponseBodyScanner = new Scanner(urlConnection.getInputStream()); // Use a ByteArrayOutputStream to store the contents of the HTTP response body responseBodyBaos = new ByteArrayOutputStream(); while(httpResponseBodyScanner.hasNextLine()) { responseBodyBaos.write(httpResponseBodyScanner.nextLine().getBytes()); } responseBodyBaos.close(); httpResponseBodyScanner.close(); // Verify contents of robots.txt String robotsContent = responseBodyBaos.toString(); if (robotsContent.trim().equals("Sitemap: http://www.techcoil.com/sitemap-index.xml")) { System.out.println("Able to retrieve robots.txt from server. Server is running fine."); // Save the robots content to file in the same directory PrintWriter printWriter = new PrintWriter("techcoil-robot.txt"); printWriter.println(robotsContent); printWriter.flush(); printWriter.close(); } else { System.out.println("Not able to retrive robots.txt from server."); } } catch(IOException ioException) { System.out.println("IOException occurred while contacting server."); ioException.printStackTrace(); } finally { if (responseBodyBaos != null) { try { responseBodyBaos.close(); } catch (IOException ioe) { System.out.println("Error while closing response body stream"); } } if (httpResponseBodyScanner != null) { httpResponseBodyScanner.close(); } } } }
I added the block that utilized an instance of java.io.PrintWriter to write the contents of Techcoil's robots.txt. With that, I had created an Java application that can be run by the Java Virtual Machine.
Running your Java application that is not contained in a jar file
To get a runnable Java application, we will first need to get the Java Compiler to compile TechcoilRobotTxtDownloader.java
:
javac TechcoilRobotTxtDownloader.java
Once the Java compiler completed its job, we will get TechcoilRobotTxtDownloader.class
in the same directory where TechcoilRobotTxtDownloader.java
is located at. TechcoilRobotTxtDownloader.class
is our runnable Java application.
To run our Java application, we will then run the following command:
java TechcoilRobotTxtDownloader
Noticed that we do not specify the .class
extension in the input parameter to our java
executable. This will tell the Java Virtual Machine to look inside of TechcoilRobotTxtDownloader.class
and run the static main
method.
So in short, we will need to provide the Java Virtual Machine with a .class file that contains a static main
method that contains the codes that will do what we wanted to do.
Understanding how the Java Virtual Machine run your Java application which is contained in a jar file
Before going into the command to prepare the jar file, it is beneficial to understand how the Java Virtual Machine runs your Java application.
By passing the name of the class (TechcoilRobotTxtDownloader) to the java
executable, the java
executable will be able to understand that there is a TechcoilRobotTxtDownloader.class
that it can find in the current directory. That is straightforward.
In the case where our Java application is contained within a jar file, we have to make sure that our jar file contains a minimal file structure as follows:
nameOfJar.jar |-- TechcoilRobotTxtDownloader.class |-- META-INF | |-- MANIFEST.MF
With that, whenever the java
executable receives a .jar
file, it will look into the META-INF
directory inside the .jar file for a MANIFEST.MF
file. The MANIFEST.MF
will need to contain a directive to tell java
executable where to find the class that contains a static main
method to run. The META-INF
directory and MANIFEST.MF
file have to named as such, they cannot be give other names.
Creating the manifest file that tells the java executable where to find the class that contains the static main method
To create a manifest file that tells the java executable where to find the class that contains the static main method, I run the following command in my shell, inside of the directory that contains TechcoilRobotTxtDownloader.class
:
nano MANIFEST.MF
I then added the following line:
Main-Class: TechcoilRobotTxtDownloader
and saved the changes.
The Main-Class
directive tells the java executable to find TechcoilRobotTxtDownloader.class
, which contains the static main
method, in the same directory as the META-INF
directory. With this information, the java executable will then be able to know that I want to run TechcoilRobotTxtDownloader.class
that is contained within the jar file.
Creating the executable jar file for running your Java application
After I had created MANIFEST.MF
, I then continued on to create the jar file. The JDK contains the jar
executable for us create jar files.
To create the jar file, I run the following command in my terminal:
jar cvfm TechcoilRobotTxtDownloader.jar MANIFEST.MF TechcoilRobotTxtDownloader.class
The first input parameter contains four instructions for the jar
executable:
- c for indicating that I want to create a jar file.
- v for indicating that I want the jar executable to report its progress to me.
- f for indicating that I wish to name my jar file myself.
- m for indicating that I want to provide my own manifest file.
With that, the jar executable will read TechcoilRobotTxtDownloader.jar
as the name for the jar
file, MANIFEST.MF
as the manifest file to include inside the META-INF directory inside of the jar
file and anything that comes afterwards will be included in the root of the jar file.
With that command, I will get the following output:
added manifest adding: TechcoilRobotTxtDownloader.class(in = 2539) (out= 1437)(deflated 43%)
This told me that the jar
executable was able to find MANIFEST.MF
and TechcoilRobotTxtDownloader.class
, placing them inside the appropriate locations within the newly created jar
file.
As an aside, in this case the manifest file that we provided for the jar
executable can be give other names. This is because the jar
executable will make sure that the manifest file is named as MANIFEST.MF
before putting it into the META-INF
directory.
Running the jar file that contains our Java application
Running the jar file from command line
To run the jar file that contains our Java application, I run the following command in my terminal:
java -jar TechcoilRobotTxtDownloader.jar
The -jar
flags tells the java executable that we are providing it a jar file that contains the Java application with a static main
method. When the command completes, I will see the output in my shell:
Able to retrieve robots.txt from server. Server is running fine.
and techcoil-robot.txt
in the same directory where TechcoilRobotTxtDownloader.jar
resides in.
Running the jar file from GUI based operating system
In a GUI based operating system, if the default application for opening .jar files is set as the Java Launcher, I will also be able to run TechcoilRobotTxtDownloader.jar
by double-clicking on the TechcoilRobotTxtDownloader.jar
icon.