My Maven Learning Notes: From JAR Files to Maven Lifecycle

I'm Saroj Bist, a self-taught web developer, learning and building with the MERN stack. I started with front-end tools like ReactJS and Tailwind CSS, and slowly stepped into full-stack development, working on real projects and solving real problems. This blog is where I share what I’m learning — from small bugs to full project insights — in a way that helps both me and anyone on a similar path.
Java projects commonly use build tools such as:
Maven
Gradle
These tools help manage dependencies, compile code, run tests, and package applications.
Understanding JAR Files
What is a JAR?
JAR (Java Archive) is a file format used to package Java applications and libraries.
When Java source code (.java files) is compiled, it becomes bytecode (.class files), which can be executed by the JVM (Java Virtual Machine).
Example:
User.java
After compilation:
User.class
The Problem Without JAR
Consider a project containing many classes:
User.java
Product.java
Order.java
Invoice.java
After compilation:
User.class
Product.class
Order.class
Invoice.class
A real project may contain hundreds or thousands of .class files.
Sharing all these files individually would be difficult and messy.
One possible solution is:
Zip all .class files
This works technically, but it is not a clean or standard approach.
How JAR Solves This Problem
A JAR file packages everything into a single file.
A JAR may contain:
.classfilesResources
Packages
Folders
Configuration files
Metadata
Example:
invoice-library.jar
Instead of sharing hundreds of files, we share one JAR file.
Using External Libraries
Suppose we want to connect our application to a database.
Instead of writing the database communication code ourselves, we can use an existing library.
Example:
mysql-connector.jar
We simply add this library to our application and use its functionality.
This is one of the main reasons JAR files are important—they allow code reuse.
Types of JAR Files
1. Library JAR (Non-Executable)
Contains reusable code.
Example:
mysql-connector.jar
jackson.jar
lombok.jar
These JARs are intended to be used by other applications.
2. Executable JAR
Contains an application that can be run directly.
Example:
java -jar app.jar
Spring Boot commonly creates executable JARs.
Libraries Depending on Other Libraries
A library may use other libraries internally.
Example:
Library A
↓
Library B
↓
Library C
To describe these dependencies, Maven uses a file called:
pom.xml
The POM file tells Maven:
Which dependencies are required
Which versions are required
Which additional libraries must be downloaded
Application Execution Flow
Java Code
+
External Libraries (JARs)
↓
Compilation
↓
Bytecode (.class)
↓
JVM
↓
Application Runs
Why Maven Exists
Suppose we need a database connector.
Without Maven:
Search for the JAR file.
Download it manually.
Add it to the project.
Download its dependencies manually.
Manage versions ourselves.
Problems:
Difficult version management
Missing dependencies
Dependency conflicts
Hard to share projects
Hard to reproduce builds
Transitive Dependencies
A dependency may depend on another dependency.
Example:
Application
↓
Spring Boot Starter Web
↓
Spring MVC
↓
Jackson
↓
Logging Libraries
Without Maven, we would need to download all of these manually.
Maven automatically handles this process.
What is Maven?
Maven is a Project Management and Build Tool.
Responsibilities:
Download dependencies
Manage dependency versions
Compile code
Run tests
Package applications
Create JAR files
Enforce standard project structure
Instead of manually downloading JARs, we simply define dependencies in:
pom.xml
Maven downloads everything automatically.
Maven Standard Project Structure
project
│
├── pom.xml
│
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ │
│ └── test
│ └── java
│
└── target
src/main/java
Contains application source code.
Example:
Controllers
Services
Repositories
Entities
src/main/resources
Contains non-Java resources.
Examples:
application.properties
application.yml
static files
templates
src/test/java
Contains test classes.
Examples:
Unit Tests
Integration Tests
The Target Folder
The target folder is generated by Maven.
Example command:
mvn compile
Maven creates:
target/
Inside:
target/classes
Maven stores compiled bytecode (.class files) here.
Does Maven Generate Bytecode?
No.
Maven itself does not compile Java code.
Instead, Maven invokes the Java compiler (javac).
Process:
Maven
↓
Calls javac
↓
javac generates bytecode
↓
.class files created
Think of Maven as the manager and javac as the worker.
Maven: "Compile these files."
javac: "Done. Here are the .class files."
What is POM?
POM stands for Project Object Model.
The pom.xml file is the heart of a Maven project. It contains all the information Maven needs to build and manage the project.
If you come from a Node.js background, you can think of:
pom.xml ≈ package.json
Both files contain project metadata, dependencies, versions, and build configuration.
Basic Structure
<project>
...
</project>
Everything in Maven is defined inside the <project> tag.
Model Version
<modelVersion>4.0.0</modelVersion>
This specifies the version of the POM model that Maven should use.
For modern Maven projects, you'll almost always see:
<modelVersion>4.0.0</modelVersion>
GAV Coordinates
Every Maven project is uniquely identified by three values:
G = Group ID
A = Artifact ID
V = Version
These are called Maven Coordinates.
Group ID
<groupId>com.saroj</groupId>
Identifies the organization, company, or developer who owns the project.
Conventionally, it follows a reversed domain name format.
Examples:
com.google
com.amazon
org.springframework
com.saroj
Think of it as a namespace to avoid naming conflicts.
Artifact ID
<artifactId>backend</artifactId>
The name of the project or library.
Examples:
spring-boot-starter-web
mysql-connector-j
backend
Version
<version>1.0.0</version>
Represents the version of the project.
Examples:
1.0.0
1.1.0
2.0.0
When the project is packaged, Maven creates something like:
backend-1.0.0.jar
Properties
The <properties> section allows us to define reusable values.
Example:
<properties>
<java.version>21</java.version>
<author.name>Saroj</author.name>
</properties>
These values can be referenced anywhere in the POM using:
${property-name}
Example:
${java.version}
${author.name}
This helps avoid duplication and makes version updates easier.
Parent POM
Many Spring Boot projects contain:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
The parent POM provides:
Dependency versions
Plugin versions
Build configurations
Spring Boot defaults
Think of it as inheriting configuration from a base class.
Dependencies
Dependencies are external libraries that our application needs.
Example:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
A dependency usually contains:
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
These values tell Maven exactly which library should be downloaded.
What Happens When We Add a Dependency?
Suppose we add:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
When Maven runs:
mvn compile
or
mvn package
it:
Reads
pom.xmlFinds required dependencies
Downloads missing JAR files
Stores them in the local Maven repository
Location:
~/.m2/repository
What If We Don't Specify a Version?
There are two possibilities.
Case 1: Version Managed by Spring Boot
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
This works because Spring Boot's parent POM already knows which version to use.
Case 2: Version Not Managed
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-http44</artifactId>
</dependency>
If Spring Boot does not manage this dependency, Maven will fail with an error similar to:
'dependencies.dependency.version' is missing
In that case, we must provide the version manually.
Transitive Dependencies
A dependency can depend on other dependencies.
Example:
Our Application
↓
Spring Boot Starter Web
↓
Spring MVC
↓
Jackson
↓
Logging Libraries
Instead of downloading all of these manually, Maven automatically resolves and downloads them.
This is called Transitive Dependency Management.
Build Section
The <build> section tells Maven how to build the project.
Example:
<build>
<plugins>
...
</plugins>
</build>
Think of:
dependencies → What my application needs
build → How Maven should build my application
Plugins
Plugins are tools that Maven uses during the build process.
Examples:
Spring Boot Maven Plugin
<artifactId>spring-boot-maven-plugin</artifactId>
Responsible for:
Creating executable Spring Boot JARs
Running Spring Boot applications
Packaging dependencies
Maven Compiler Plugin
<artifactId>maven-compiler-plugin</artifactId>
Responsible for:
Compiling Java source code
Configuring Java version
Running annotation processors such as Lombok
Maven Lifecycle
Maven follows a predefined build lifecycle. A lifecycle is simply a sequence of phases that Maven executes to build, test, package, and deploy a project.
Common Maven lifecycle phases:
validate → compile → test → package → verify → install → deploy
Maven Lifecycle Overview
Source Code
↓
validate
↓
compile
↓
test
↓
package
↓
verify
↓
install
↓
deploy
Each phase has a specific responsibility.
1. validate
Validates that the project structure and configuration are correct.
Examples:
Checks whether
pom.xmlis valid.Ensures required project information is available.
Verifies that Maven can proceed with the build.
Command:
mvn validate
2. compile
Compiles Java source code into bytecode.
Process:
.java
↓
javac
↓
.class
Output location:
target/classes
Command:
mvn compile
Important:
Maven does not generate bytecode itself.
Instead, Maven invokes the Java compiler (javac) to compile the code.
3. test
Runs unit tests located inside:
src/test/java
Example:
@Test
void shouldCreateUser() {
...
}
Command:
mvn test
If tests fail:
BUILD FAILURE
Maven stops the build process.
4. package
Packages the application into a distributable format.
Common outputs:
JAR
WAR
Output location:
target/
Example:
target/gold-jar-backend-0.0.1-SNAPSHOT.jar
Command:
mvn package
For Spring Boot projects, the result is usually an executable JAR:
java -jar app.jar
5. verify
Performs additional verification after packaging.
Common examples:
Integration tests
Code quality checks
Security scans
JaCoCo code coverage validation
Custom plugin validations
Command:
mvn verify
Many teams use this phase in CI/CD pipelines.
6. install
Copies the packaged artifact into the local Maven repository.
Location:
~/.m2/repository
Command:
mvn install
Example flow:
Project
↓
package
↓
app.jar
↓
~/.m2/repository
This allows other local Maven projects to use your artifact as a dependency.
7. deploy
Publishes the artifact to a remote Maven repository.
Examples:
Nexus Repository
Artifactory
Maven Central
Command:
mvn deploy
Example flow:
Project
↓
package
↓
install
↓
Remote Repository
Now other developers or servers can download the artifact.
What About Site?
Maven also provides a Site lifecycle.
Command:
mvn site
Purpose:
Generate project documentation and reports.
Examples:
Dependency reports
Test reports
Plugin reports
Project information
Code coverage reports
Output location:
target/site
Most modern Spring Boot projects rarely use this feature, but it is still available.
Maven Executes Previous Phases Automatically
One important rule:
When you run a phase, Maven executes all previous phases automatically.
Example:
mvn package
Actually runs:
validate
↓
compile
↓
test
↓
package
Similarly:
mvn install
Runs:
validate
↓
compile
↓
test
↓
package
↓
verify
↓
install


