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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
