Spring Boot Deployment: Jar vs War – Key Differences Explained

When a Spring Boot project is packaged as a jar it runs with the embedded Tomcat using the application's own configuration, while a war package relies on an external Tomcat container, adopts the container's settings such as the default 8080 port, and requires additional Maven configuration and a ServletInitializer class.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
Spring Boot Deployment: Jar vs War – Key Differences Explained

The article starts with a real‑world issue: a Spring Boot project built with mvn install as a jar runs directly via java -jar on any machine that has a JDK, using the port defined in server.port. When the same project is repackaged as a war and deployed to a standalone Tomcat, the application runs on Tomcat’s default port 8080 and the URL gains the context path of the war file.

It explains why this happens. A jar package contains Spring Boot’s embedded Tomcat, so the application starts its own server and respects the configuration inside application.properties. A war package disables the embedded server; Tomcat provided by the deployment environment takes over, ignoring the internal configuration and applying its own defaults.

The article then gives a brief historical background: early web applications used CGI, then Sun introduced the Servlet API and the WAR (Web Application Archive) format as the standard deployment unit for Java EE. Later, lightweight servlet containers like Jetty and embedded Tomcat emerged, leading to the modern “use jar, not war” micro‑service trend.

Packaging as a Jar

Create a Spring Starter Project in IDE; the default packaging is jar.

Typical pom.xml (excerpt):

<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
  </parent>
  <groupId>com.example</groupId>
  <artifactId>demo</artifactId>
  <version>0.0.1‑SNAPSHOT</version>
  <properties>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

Run mvn clean package in a terminal; the resulting demo‑0.0.1‑SNAPSHOT.jar appears in the target directory and can be started with java -jar.

Packaging as a War

Add a ServletInitializer class (placed in the same package as the main application) that extends SpringBootServletInitializer and overrides configure.

public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoApplication.class);
    }
}

Modify pom.xml:

Set <packaging>war</packaging>.

Exclude the embedded Tomcat starter:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Add servlet API dependencies required by an external container:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-servlet-api</artifactId>
    <version>8.0.36</version>
    <scope>provided</scope>
</dependency>

Run mvn clean package again; a demo‑0.0.1‑SNAPSHOT.war is generated. Deploy the war file to $TOMCAT_HOME/webapps and start Tomcat. The application will be accessible at http://<em>host</em>:8080/<em>war‑name</em>/….

If the project is created with packaging=war from the beginning, Spring Initializr generates the ServletInitializer automatically, and the pom already contains the necessary changes.

In summary, jar packaging gives a self‑contained executable with an embedded server, suitable for micro‑services, while war packaging produces a deployable archive that relies on an external servlet container, requiring additional Maven configuration and a servlet initializer class.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

mavenSpring BootPackagingTomcatjarwar
Java Architect Handbook
Written by

Java Architect Handbook

Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.