WAR vs JAR Files

Java packaging formats explained

← Back to Index

What is an Archive File?

An archive file is simply a single file that contains many other files bundled together. Think of it like a ZIP file—because that's exactly what Java archives are!

Moving Box Analogy:

Imagine you're moving to a new house. Instead of carrying thousands of individual items one at a time, you pack them into boxes. Each box:

  • Contains many items organized in a specific way
  • Has a label describing its contents
  • Is easy to move as a single unit
  • Can be unpacked to access individual items

Java archives (JAR and WAR) work the same way—they bundle all your application's files into a single, portable package.

Why Not Just Use ZIP Files?

Java archives ARE ZIP files with extra features:

# You can actually open any JAR/WAR with a ZIP tool:
unzip myapp.jar -d extracted/

# Or use Java's jar command:
jar -tf myapp.jar        # List contents
jar -xf myapp.jar        # Extract contents

JAR Files: Java Archive

A JAR (Java Archive) file is the standard packaging format for Java applications and libraries. It bundles compiled Java classes, resources, and metadata into a single file.

JAR File Structure

myapp.jar
├── META-INF/
│   ├── MANIFEST.MF          # Manifest file (metadata)
│   └── maven/               # (Optional) Maven info
├── com/
│   └── example/
│       ├── Main.class       # Compiled Java classes
│       ├── Service.class
│       └── util/
│           └── Helper.class
├── application.properties   # Configuration files
└── static/
    └── logo.png             # Static resources

The MANIFEST.MF File

The manifest is a special file that contains metadata about the JAR:

# META-INF/MANIFEST.MF

Manifest-Version: 1.0
Created-By: 17.0.1 (Oracle Corporation)
Main-Class: com.example.Main
Class-Path: lib/gson-2.9.0.jar lib/commons-lang3-3.12.0.jar
Implementation-Title: My Application
Implementation-Version: 1.0.0

Types of JAR Files

Type Description How to Run
Library JAR Reusable code (no Main-Class) Add to classpath
Executable JAR Has Main-Class in manifest java -jar app.jar
Fat/Uber JAR Includes all dependencies java -jar app.jar

Creating JAR Files with Maven

<!-- pom.xml -->
<packaging>jar</packaging>

<build>
    <plugins>
        <!-- Standard JAR -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.example.Main</mainClass>
                        <addClasspath>true</addClasspath>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <!-- Fat JAR with shade plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals><goal>shade</goal></goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

WAR Files: Web Application Archive

A WAR (Web Application Archive) file is a specialized packaging format for Java web applications. It contains everything needed to deploy a web application to a servlet container.

WAR = JAR + Web Structure

A WAR file is essentially a JAR file with a specific directory structure that servlet containers understand. This structure defines where to find servlets, JSP files, static resources, and dependencies.

WAR File Structure

mywebapp.war
├── META-INF/
│   └── MANIFEST.MF
├── WEB-INF/                    # PROTECTED - Not accessible via URL!
│   ├── web.xml                 # Deployment descriptor
│   ├── classes/                # Compiled Java classes
│   │   └── com/
│   │       └── example/
│   │           ├── HomeServlet.class
│   │           └── ProductServlet.class
│   └── lib/                    # JAR dependencies
│       ├── gson-2.9.0.jar
│       └── mysql-connector-8.0.jar
├── index.html                  # PUBLIC - /mywebapp/index.html
├── css/
│   └── style.css               # PUBLIC - /mywebapp/css/style.css
├── js/
│   └── app.js                  # PUBLIC - /mywebapp/js/app.js
└── images/
    └── logo.png                # PUBLIC - /mywebapp/images/logo.png

The WEB-INF Directory: Understanding Protection

The WEB-INF directory is special—its contents cannot be accessed directly by clients via HTTP requests:

# What users CAN access (outside WEB-INF):
http://localhost:8080/mywebapp/index.html        ✓ Returns HTML
http://localhost:8080/mywebapp/css/style.css     ✓ Returns CSS

# What users CANNOT access (inside WEB-INF):
http://localhost:8080/mywebapp/WEB-INF/web.xml   ✗ 404 or 403
http://localhost:8080/mywebapp/WEB-INF/classes/  ✗ 404 or 403

# WHY? Security! WEB-INF contains:
# - Configuration with database credentials
# - Compiled code that could be decompiled
# - Libraries that could reveal vulnerabilities
Security Best Practice

Always put sensitive files (JSP templates, configuration) inside WEB-INF/. Use servlets to forward requests to protected resources.

Creating WAR Files with Maven

<!-- pom.xml -->
<packaging>war</packaging>

<dependencies>
    <!-- Servlet API - provided by container -->
    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>6.0.0</version>
        <scope>provided</scope>  <!-- Not included in WAR -->
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
    </plugins>
</build>

JAR vs WAR: Complete Comparison

Aspect JAR WAR
Full Name Java Archive Web Application Archive
Purpose General Java apps/libraries Web applications
Structure META-INF/ + classes + resources WEB-INF/ + public resources
Deployment java -jar or classpath Deploy to servlet container
Dependencies Optional (fat JAR) or external Always in WEB-INF/lib
Protected Area None WEB-INF/ (hidden from web)
Hot Deployment Requires restart Supported by containers

Spring Boot: JAR or WAR?

Spring Boot applications can be packaged as either JAR or WAR:

Spring Boot JAR (Recommended)

<packaging>jar</packaging>

# Run with:
java -jar myapp-1.0.0.jar

# Benefits:
# - Embedded Tomcat included
# - Simple deployment
# - Cloud-native friendly

Spring Boot WAR (For External Container)

<packaging>war</packaging>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>  <!-- Don't include Tomcat -->
</dependency>

// Main class for WAR deployment
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder app) {
        return app.sources(MyApplication.class);
    }
}

When to Use Each Format

Use Case Recommended Reason
New Spring Boot app JAR Simpler, embedded container
Cloud deployment JAR Better for Docker
Legacy system WAR May require existing container
Corporate standard WAR WebLogic/WebSphere requirement
Microservices JAR Independent deployment
Reusable library JAR Not a web application

EAR Files: Enterprise Archive

For completeness, EAR (Enterprise Archive) files bundle multiple modules (WARs, JARs) into a single deployable unit for full application servers:

enterprise-app.ear
├── META-INF/
│   ├── MANIFEST.MF
│   └── application.xml    # Defines modules
├── web-module.war         # Web tier
├── ejb-module.jar         # EJB tier
└── lib/
    └── shared-utils.jar   # Shared libraries

Modern Perspective: EAR files were common in the Java EE era but are less common today. Modern architectures favor microservices (independent JARs), Spring Boot (embedded containers), or containers (Docker).

Common Issues and Troubleshooting

1. "No main manifest attribute"

# Error:
java -jar myapp.jar
no main manifest attribute, in myapp.jar

# Solution: Add Main-Class to manifest in pom.xml
<manifest>
    <mainClass>com.example.Main</mainClass>
</manifest>

2. ClassNotFoundException in Fat JAR

# Error: Dependency classes not found at runtime

# Cause: Dependencies not included in JAR
# Solution: Use maven-shade-plugin for fat JAR

# Check what's in your JAR:
jar -tf myapp.jar | grep gson
# Should show com/google/gson/... if using fat JAR

3. javax vs jakarta Package Issues

# Error in Tomcat 10+:
java.lang.NoClassDefFoundError: javax/servlet/Servlet

# Cause: Using javax.servlet with Tomcat 10+ (requires jakarta)

# Solution: Update imports and dependencies
# OLD: import javax.servlet.*;
# NEW: import jakarta.servlet.*;

Summary

  • JAR: General-purpose Java archive for applications and libraries
  • WAR: Web application archive with specific structure for servlet containers
  • WEB-INF/: Protected directory in WAR, inaccessible via HTTP
  • Fat JAR: JAR with all dependencies bundled inside
  • Embedded containers: Modern approach, container inside your JAR
  • Spring Boot JAR: Preferred for new applications
  • WAR for legacy: Use when external container is required
  • MANIFEST.MF: Contains metadata, Main-Class for executables