How to Package and Run a Simple Java Command-Line Application with Dependencies Using Maven: A Beginner's Guide
Java is a versatile language, but managing dependencies and packaging applications can be daunting for beginners. Manually downloading JAR files, ensuring they’re in the classpath, and organizing project structure often leads to frustration. Enter Maven—a build automation tool that simplifies project management, dependency handling, and packaging.
In this guide, we’ll walk through creating a simple Java command-line application, adding an external dependency (e.g., Apache Commons Lang for utility functions), and using Maven to package and run the app. By the end, you’ll understand how Maven streamlines dependency management and build processes, even for small projects.
Table of Contents#
- Prerequisites
- Setting Up a Maven Project
- Writing the Java Code
- Adding Dependencies to the POM
- Configuring the POM for Packaging
- Building the Project
- Running the Executable JAR
- Troubleshooting Common Issues
- References
Prerequisites#
Before we start, ensure you have the following installed:
-
Java Development Kit (JDK): Maven requires Java to run. Install JDK 8 or later (e.g., Adoptium Temurin).
Verify with:java -version(should show a JDK version, not just JRE). -
Maven: Download from Maven’s official site and follow installation steps for your OS.
Verify with:mvn -version(should show Maven and Java versions). -
Text Editor/IDE: Use VS Code, IntelliJ IDEA, Eclipse, or even Notepad++. For simplicity, we’ll use VS Code here.
Setting Up a Maven Project#
Maven uses a Project Object Model (POM) file (pom.xml) to define project configuration, dependencies, and build steps. Let’s create a new Maven project from scratch.
Step 1: Generate a Maven Project#
Open your terminal/command prompt and run the following command to generate a basic project structure using Maven’s maven-archetype-quickstart (a template for simple apps):
mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseWhat do these parameters mean?#
groupId: A unique identifier for your project (e.g.,com.examplefor personal projects).artifactId: The name of your project (e.g.,my-app).archetypeArtifactId: The template to use (maven-archetype-quickstartcreates a basic Java project with a main class and test).
Step 2: Explore the Project Structure#
Maven will create a my-app folder with this structure:
my-app/
├── pom.xml # Project configuration (Maven POM)
├── src/
│ ├── main/
│ │ └── java/
│ │ └── com/
│ │ └── example/
│ │ └── App.java # Main application class
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── AppTest.java # Test class
└── target/ # Auto-generated build output (created after building)
The key file here is pom.xml—we’ll modify this to add dependencies and build settings.
Writing the Java Code#
Let’s enhance the auto-generated App.java to include a dependency. We’ll use Apache Commons Lang, a popular library for string manipulation, to demonstrate how dependencies work.
Step 1: Update the Main Class#
Open src/main/java/com/example/App.java in your editor. Replace the existing code with:
package com.example;
import org.apache.commons.lang3.StringUtils; // Import from Apache Commons Lang
public class App {
public static void main(String[] args) {
String name = "maven beginner";
// Use Apache Commons Lang's StringUtils to capitalize the string
String capitalizedName = StringUtils.capitalize(name);
System.out.println("Hello, " + capitalizedName + "!");
System.out.println("This app uses Apache Commons Lang!");
}
}What does this code do?#
- It imports
StringUtilsfrom Apache Commons Lang. - It takes a string (
"maven beginner"), capitalizes it usingStringUtils.capitalize(), and prints a message.
Adding Dependencies to the POM#
Our code uses StringUtils, which isn’t part of Java’s standard library. We need to tell Maven to download this dependency (Apache Commons Lang) from Maven Central (a repository of Java libraries).
Step 1: Find Dependency Coordinates#
To add a dependency, you need its groupId, artifactId, and version. Find these on Maven Central:
- Go to Maven Central Search.
- Search for "Apache Commons Lang".
- Select the latest stable version (e.g.,
3.14.0at the time of writing). - Copy the Maven dependency snippet (e.g., for 3.14.0):
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>Step 2: Add the Dependency to pom.xml#
Open pom.xml and paste the dependency inside the <dependencies> section (create the section if it doesn’t exist):
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- Apache Commons Lang dependency -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<!-- JUnit for testing (auto-generated by the archetype) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>Maven will automatically download this dependency when you build the project.
Configuring the Maven POM for Packaging#
To run our app as a standalone JAR, we need to:
- Specify the main class (so Java knows where to start).
- Package dependencies into the JAR (or ensure they’re available).
Step 1: Set the Main Class with maven-jar-plugin#
By default, Maven creates a JAR but doesn’t specify the main class in the JAR’s manifest. Add the maven-jar-plugin to the <build> section of pom.xml to fix this:
<build>
<plugins>
<!-- Configure JAR manifest to specify main class -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.App</mainClass> <!-- Full path to your main class -->
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>Step 2: Package Dependencies with maven-assembly-plugin#
The default JAR only contains your project’s code, not dependencies like Apache Commons Lang. To include dependencies (create a "fat JAR"), use the maven-assembly-plugin:
Add this plugin below the maven-jar-plugin in the <plugins> section:
<!-- Package all dependencies into a single JAR (fat JAR) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <!-- Includes dependencies -->
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.example.App</mainClass> <!-- Same main class as before -->
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase> <!-- Run during the "package" build phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>Building the Project#
Now, let’s build the project. Run this command in the terminal from the my-app directory:
mvn clean packageWhat does this do?#
clean: Deletes thetarget/folder (old build files).package: Compiles your code, runs tests, and packages the app into a JAR.
Verify the Build Output#
After the build succeeds, check the target/ folder. You’ll see two JARs:
my-app-1.0-SNAPSHOT.jar: Default JAR (without dependencies).my-app-1.0-SNAPSHOT-jar-with-dependencies.jar: Fat JAR (with all dependencies included).
Running the Executable JAR#
Use the fat JAR to run the app (since it includes dependencies):
java -jar target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jarExpected Output:#
Hello, Maven beginner!
This app uses Apache Commons Lang!
Troubleshooting Common Issues#
1. "Could not find or load main class"#
- Fix: Ensure the
mainClassinmaven-jar-pluginmatches your class path (e.g.,com.example.App).
2. NoClassDefFoundError for StringUtils#
- Fix: Use the fat JAR (
-jar-with-dependencies) instead of the default JAR.
3. Build Fails with "Compilation Error"#
- Fix: Check for typos in
App.java(e.g., missing imports or incorrect method names likeStringUtils.capitalize).
4. Maven Not Found#
- Fix: Ensure Maven is installed and added to your system’s
PATHenvironment variable.
References#
- Maven Official Documentation
- Maven Central Repository
- Apache Commons Lang
- Maven Assembly Plugin
- Installing JDK
Congratulations! You’ve built and run a Java command-line app with dependencies using Maven. Maven simplifies dependency management and packaging, making it easier to scale projects. Experiment with other dependencies (e.g., Gson for JSON parsing) to explore more! 🚀