Project: Spring Boot WAR on Tomcat

Introduction

This capstone converts a minimal Spring Boot 3 REST app from executable JAR thinking to WAR on external Tomcat, deploys beside your Servlet WAR, and compares verification steps with java -jar. It applies Spring Boot WAR on Tomcat end-to-end.

Prerequisites

Project Goals

  • Boot app demo-api.war with GET /api/status
  • Deploy to Tomcat at /demo-api
  • Checklist comparing JAR vs WAR deploy

Step 1: Create Boot WAR Project

bash
# Or start from start.spring.io: Maven, Jar→change to War, Spring Web, Boot 3, Java 17
mkdir -p demo-api/src/main/java/com/example/demo
mkdir -p demo-api/src/main/resources
cd demo-api

pom.xml (essential parts):

DemoApplication.java:

java
package com.example.demo;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

ServletInitializer.java:

java
package com.example.demo;
 
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 
public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DemoApplication.class);
    }
}

StatusController.java:

application.properties:

properties
server.forward-headers-strategy=framework

Step 2: Build and Deploy

bash
mvn clean package
export CATALINA_HOME=/opt/tomcat
$CATALINA_HOME/bin/shutdown.sh
cp target/demo-api.war $CATALINA_HOME/webapps/
# blog-api.war can remain — multiple WARs coexist
$CATALINA_HOME/bin/startup.sh
tail -30 $CATALINA_HOME/logs/catalina.$(date +%Y-%m-%d).log

Verify:

bash
curl -s http://127.0.0.1:8080/demo-api/api/status

Expected JSON with external-tomcat.

Step 3: JAR vs WAR Comparison Checklist

CheckExecutable JARWAR on Tomcat
Run commandjava -jar demo.jarstartup.sh (Tomcat)
Tomcat in artifactEmbedded in JARprovided — external
Context pathserver.servlet.context-path or /WAR name demo-api/demo-api
Configapplication.ymlSame
LogsConsole / file per applogs/localhost.*.log
Multiple appsOne JAR per processMultiple WARs one JVM
Nginx upstreamproxy_pass :8080Same — mind context paths

Step 4: Nginx Location (If Using Project 18)

Add to Nginx server block:

nginx
location /demo-api/ {
    proxy_pass http://127.0.0.1:8080/demo-api/;
    include /etc/nginx/proxy_params;
}
bash
curl -H "Host: app.example.com" http://127.0.0.1/demo-api/api/status

Step 5: Actuator (Optional)

Add spring-boot-starter-actuator, configure exposure, hit:

bash
curl http://127.0.0.1:8080/demo-api/actuator/health

Restrict public access in production.

Acceptance Checklist

  • ServletInitializer present
  • Tomcat starter provided
  • Boot starts in Tomcat logs without ClassNotFoundException
  • /demo-api/api/status returns JSON
  • Can explain one JAR vs WAR tradeoff from checklist

Troubleshooting

IssueFix
404URL must include /demo-api prefix
Works as JAR, fails as WARMissing ServletInitializer
NoSuchMethodErrorEmbedded Tomcat not provided

Track Complete

You have deployed plain Servlet WAR, external docBase, Nginx + Tomcat, and Spring Boot WAR. Continue with Troubleshooting and the chapter index.