I would like to create simple "Hello World" Spring MVC web app without Spring Boot and deploy it to Tomcat. I build WAR file and deploy it to standalone Tomcat. When I open url http://localhost:8080/simple-spring-mvc/home I'm getting 404 from Tomcat. There are no errors in catalina out and other log files.
I'm using the following versions: Tomcat 11; Spring MVC 6.2.4
Project Directory Structure:
simple-spring-mvc/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ ├── config/
│ │ │ │ ├── WebAppInitializer.java
│ │ │ │ └── WebConfig.java
│ │ │ └── controller/
│ │ │ └── HomeController.java
│ │ └── webapp/
│ │ └── WEB-INF/
│ │ └── views/
│ │ └── home.jsp
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>com.example</groupId>
<artifactId>simple-spring-mvc</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<java.version>21</java.version>
<spring.version>6.2.4</spring.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSP API -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>simple-spring-mvc</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
</plugin>
</plugins>
</build>
</project>
WebAppInitializer:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
WebConfig:
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
registry.viewResolver(resolver);
}
}
HomeController:
@Controller
@RequestMapping("/home")
public class HomeController {
@GetMapping()
public String home(Model model) {
model.addAttribute("message", "Hello World!");
return "home";
}
}
home.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Spring MVC Demo</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
I have duplicated your project here and it works as is - https://github.com/KoosieDeMoer/annoyingtomcat404
Clone it, build it (mvn install), drop the warfile in webapps and compare logs:
catalina start:
catalina start
Using CATALINA_BASE: "C:\apache-tomcat-10.1.39"
Using CATALINA_HOME: "C:\apache-tomcat-10.1.39"
Using CATALINA_TMPDIR: "C:\apache-tomcat-10.1.39\temp"
Using JRE_HOME: ""C:\java\jdk-21.0.5+11""
Using CLASSPATH: "C:\apache-tomcat-10.1.39\bin\bootstrap.jar;C:\apache-tomcat-10.1.39\bin\tomcat-juli.jar"
Using CATALINA_OPTS: ""
tomcat sdtout:
19-Mar-2025 15:06:24.028 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/10.1.39
19-Mar-2025 15:06:24.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Mar 4 2025 19:02:32 UTC
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 10.1.39.0
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Windows 10
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 10.0
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: C:\java\jdk-21.0.5+11
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 21.0.5+11-adhoc.Administrator.jdk21u
19-Mar-2025 15:06:24.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: OpenLogic
19-Mar-2025 15:06:24.035 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: C:\apache-tomcat-10.1.39
19-Mar-2025 15:06:24.035 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: C:\apache-tomcat-10.1.39
19-Mar-2025 15:06:24.056 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=C:\apache-tomcat-10.1.39\conf\logging.properties
19-Mar-2025 15:06:24.056 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
19-Mar-2025 15:06:24.056 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
19-Mar-2025 15:06:24.056 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
19-Mar-2025 15:06:24.057 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dsun.io.useCanonCaches=false
19-Mar-2025 15:06:24.057 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED
19-Mar-2025 15:06:24.057 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
19-Mar-2025 15:06:24.057 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED
19-Mar-2025 15:06:24.057 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.util=ALL-UNNAMED
19-Mar-2025 15:06:24.058 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
19-Mar-2025 15:06:24.058 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
19-Mar-2025 15:06:24.058 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=C:\apache-tomcat-10.1.39
19-Mar-2025 15:06:24.058 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=C:\apache-tomcat-10.1.39
19-Mar-2025 15:06:24.059 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=C:\apache-tomcat-10.1.39\temp
19-Mar-2025 15:06:24.199 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [2.0.8] using APR version [1.7.4].
19-Mar-2025 15:06:24.219 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 3.0.14 4 Jun 2024]
19-Mar-2025 15:06:24.520 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
19-Mar-2025 15:06:24.560 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [724] milliseconds
19-Mar-2025 15:06:24.625 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
19-Mar-2025 15:06:24.625 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/10.1.39]
19-Mar-2025 15:06:24.648 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [C:\apache-tomcat-10.1.39\webapps\simple-spring-mvc.war]
19-Mar-2025 15:06:25.863 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
19-Mar-2025 15:06:26.027 INFO [main] org.springframework.web.servlet.FrameworkServlet.initServletBean Initializing Servlet 'dispatcher'
19-Mar-2025 15:06:26.768 INFO [main] org.springframework.web.servlet.FrameworkServlet.initServletBean Completed initialization in 739 ms
19-Mar-2025 15:06:26.781 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [C:\apache-tomcat-10.1.39\webapps\simple-spring-mvc.war] has finished in [2,131] ms
19-Mar-2025 15:06:26.783 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\apache-tomcat-10.1.39\webapps\docs]
19-Mar-2025 15:06:26.834 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\apache-tomcat-10.1.39\webapps\docs] has finished in [52] ms
19-Mar-2025 15:06:26.834 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\apache-tomcat-10.1.39\webapps\examples]
19-Mar-2025 15:06:28.473 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\apache-tomcat-10.1.39\webapps\examples] has finished in [1,639] ms
19-Mar-2025 15:06:28.474 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\apache-tomcat-10.1.39\webapps\host-manager]
19-Mar-2025 15:06:28.548 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\apache-tomcat-10.1.39\webapps\host-manager] has finished in [75] ms
19-Mar-2025 15:06:28.549 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\apache-tomcat-10.1.39\webapps\manager]
19-Mar-2025 15:06:28.626 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\apache-tomcat-10.1.39\webapps\manager] has finished in [76] ms
19-Mar-2025 15:06:28.626 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [C:\apache-tomcat-10.1.39\webapps\ROOT]
19-Mar-2025 15:06:28.670 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [C:\apache-tomcat-10.1.39\webapps\ROOT] has finished in [44] ms
19-Mar-2025 15:06:28.674 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
19-Mar-2025 15:06:28.709 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [4147] milliseconds