Issue
TL;DR: I have Spring MVC helloworld app that works on Tomcat 9. The same app on Tomcat 10 gives a 404 error for web request mappings.
The Problem
When deploying a Spring MVC 5 helloworld app to Tomcat 10, the app gives a 404 error for web request mappings. The same helloworld app works on Tomcat 9. It displays the helloworld message on Tomcat 9.
What I Expected
I expected the app to display the helloworld message on Tomcat 10.
Environment
- MS Windows 10
- Tomcat 10.0.2
- Spring MVC 5.3.3
Research I Performed
I researched in the Spring Reference Manual, Section on Web Servlet. I also tested Spring MVC Tutorials onlines. These tutorials worked on Tomcat 9. However, the same tutorials failed on Tomcat 10. I also performed google search on Tomcat 10. I saw references to Jakarta EE but not sure if this is the source of the issue. Java EE 8 and Jakarta EE 8 are backwards compatible.
How to Reproduce
I created a very basic helloword project to test this out. Here is the code that I'm using for the project.
pom.xml
<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.spring</groupId>
<artifactId>example-spring</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
</plugin>
</plugins>
</build>
</project>
ProjectInitializer.java
package com.example;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class ProjectInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { PureJavaConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
}
PureJavaConfig.java
package com.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan("com.example")
public class PureJavaConfig {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setSuffix(".jsp");
resolver.setPrefix("/WEB-INF/jsp/");
return resolver;
}
}
TutorialController.java
package com.example;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TutorialController {
@GetMapping("/")
public String home() {
return "home";
}
}
home.jsp
<html>
<body>Hello World of Spring! <%= java.time.LocalDateTime.now() %></body>
</html>
This projects runs okay on Tomcat 9. It displays the helloworld message. However, when I run on Tomcat 10, I get a 404 error message.
Solution
TL;DR: Spring MVC 5 does not run on Tomcat 10 because of the package renaming from javax.*
to jakarta.*
.
After further research, I was able to find the answer to my question. Spring MVC 5 does not work on Tomcat 10. This is because Tomcat 10 is based on Jakarta EE 9 where package names for APIs have changed from javax.*
to jakarta.*
.
Tomcat 10 mentioned this on the download webpage:
Users of Tomcat 10 onwards should be aware that, as a result of the move from Java EE to Jakarta EE as part of the transfer of Java EE to the Eclipse Foundation, the primary package for all implemented APIs has changed from
javax.*
tojakarta.*
. This will almost certainly require code changes to enable applications to migrate from Tomcat 9 and earlier to Tomcat 10 and later.
For Spring MVC 5, the Spring MVC DispatcherServlet has a dependency on the javax.servlet.*
package namespace. This is using the Java EE 8 javax
package naming. Since Tomcat 10 is based on Jakarta EE 9, the packages for javax
naming are not supported. This explains why Spring MVC 5 does not work on Tomcat 10.
There are github issues filed against the Spring Framework regarding this:
Spring core 5 is not starting on tomcat 10
Support for Jakarta EE 9 (annotations and interfaces in jakarta.* namespace)
In my case, instead of migrating to Tomcat 10, I will stay on Tomcat 9 until the Spring framework is upgraded to Jakarta EE 9.
Answered By - knelson59406