Why Does My Spring Boot App Behave Differently as JAR vs WAR? Understanding Embedded and External Tomcat
This article explains why a Spring Boot application runs with the configured port when packaged as a JAR using the embedded Tomcat, but switches to Tomcat's default port and context path when deployed as a WAR, and provides step‑by‑step instructions to package and deploy both formats along with historical context and technical differences.
The author encountered a strange issue where a Spring Boot project packaged as a JAR runs with the embedded Tomcat on one machine, but when the same project is packaged as a WAR and deployed to an external Tomcat, the port and context path change.
Running a JAR starts the embedded Tomcat, so the application uses the port defined in application.properties (e.g., server.port=8090). Deploying a WAR to an external Tomcat disables the embedded server; the external Tomcat's configuration (default port 8080 and context path based on the WAR name) takes precedence.
Brief historical background: early CGI scripts gave way to Sun's servlet and JSP standards, leading to Java EE and servlet containers like Tomcat. Later, lightweight embedded servers such as Jetty and Undertow emerged, and the micro‑service trend promoted "use JAR, not WAR" to avoid heavyweight containers.
Differences between JAR and WAR
WAR is a web module containing a WEB-INF directory and can be deployed directly to a servlet container.
JAR usually contains only class files and a Main-Class entry, allowing execution via java -jar.
WAR packages a complete web application; JAR is often used for reusable libraries or components.
JAR files are ZIP‑based archives that can also hold signed content and resources.
Key characteristics of JAR
Security : can be digitally signed to verify integrity.
Reduced download time : an applet bundled in a JAR can be downloaded in a single HTTP request.
Compression : reduces storage size.
Platform extensions : Java Extensions Framework uses JARs to add functionality to the core platform.
WAR file is a compressed representation of a complete web application, excluding the root of the web‑application directory hierarchy.
Conditions for building a WAR
Create the correct web‑application directory hierarchy.
Add a WEB-INF directory with classes and lib sub‑directories.
Place servlet class files in WEB-INF/classes and library JARs in WEB-INF/lib.
Put JSP or static HTML files under the context root.
Create a META-INF directory containing a context.xml file.
Packaging a Spring Boot project as a JAR
Create a new Spring Starter Project in the IDE (packaging defaults to jar).
Run mvn clean package in a terminal; the resulting JAR appears in the target directory.
Packaging the same project as a WAR
Add a ServletInitializer class in the same package as the main application.
Modify pom.xml to change <packaging>war</packaging>.
Exclude the embedded Tomcat starter and add dependencies for javax.servlet-api and tomcat-servlet-api with provided scope.
Keep other Spring Boot starters as needed (e.g., spring-boot-starter-web, spring-boot-starter-thymeleaf).
Run mvn clean package again; the generated WAR can be placed in Tomcat's webapps directory and started.
<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/xsd/maven-4.0.0.xsd">
<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>
<packaging>war</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
<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>After building, place the WAR in Tomcat's webapps directory and start Tomcat to run the application.
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 Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
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.
