Spring Boot - custom 404 page with standalone tomcat
Data Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.
Introduction
A custom 404 page is simple in embedded Spring Boot, but WAR deployment to standalone Tomcat adds extra moving parts. Static resources, template lookup, and container-level mappings can all affect what users see when a route is missing. The most reliable approach is to start with Spring Boot conventions, then add custom logic only where behavior must differ.
How Spring Boot Resolves 404 Responses
Spring Boot has an internal error flow that handles exceptions and missing routes. When the status is 404, it tries to resolve an error view from known locations. If that lookup fails, you usually get a default error response.
For an MVC app with Thymeleaf, use templates/error/404.html. For static HTML, use public/error/404.html.
In many projects, only one of these is needed. If you already render server templates, keep the page in templates/error/404.html so it can reuse your app layout.
WAR Packaging for Standalone Tomcat
The most common failure is not Java code. It is missing resources in the WAR. A local run can work while deployed Tomcat returns its own default 404 because your custom file was not packaged.
Check your artifact directly:
If no output appears, your page is not inside the WAR. Review your build setup and resource includes. A minimal Maven setup that keeps resources intact looks like this:
Also verify your app is built as war and has the Spring Boot Tomcat dependency set correctly for external container deployment.
Configuration for a Predictable 404 Experience
Start with standard error properties. Disable the whitelabel response so your page or JSON body is always used.
When you need finer behavior, add a resolver that only handles 404 and leaves other statuses untouched.
This keeps behavior explicit and avoids replacing handling for 500 responses accidentally.
Returning HTML for Browsers and JSON for APIs
Mixed applications often need two styles of 404 output. Browsers should get a readable page, while API clients should get structured JSON.
One practical pattern is to keep HTML view resolution for normal web routes and add a JSON handler for API paths.
If you use this pattern, enable throwing NoHandlerFoundException with the matching MVC settings in your application configuration.
Testing the Deployed Behavior
Unit tests are useful, but you also need at least one deploy-like check. Verify status code and response body type.
After that, run a smoke test against Tomcat itself, not just local embedded mode.
Common Pitfalls
- Custom page works in local run but not in Tomcat because
error/404files were excluded from WAR packaging. Confirm artifact contents before debugging controllers. - API clients receiving HTML 404 because only MVC page rendering was configured. Add API-specific JSON handling for missing routes.
- Returning
ModelAndViewfor every status in a resolver. Restrict custom logic to 404 so 500 diagnostics are not hidden. - Reverse proxy sends 404 before request reaches Spring app. Test both direct Tomcat endpoint and external ingress URL.
- Relative links in the error page breaking under non-root context paths. Use context-aware links and verify assets load under deployed path.
Summary
- Keep custom 404 handling convention-first with
error/404resources. - Validate WAR packaging early to avoid false code-level debugging.
- Split browser and API error responses when serving both clients.
- Limit custom resolver scope so non-404 errors remain visible and debuggable.
- Add deploy-level tests to guarantee the same behavior in standalone Tomcat.
Related reading
- Spring boot - custom variables in Application.properties
- Spring Boot - Different systems eureka , zuul, ribbon, nginx, used for what?
- Spring Boot - Different systems eureka , zuul, ribbon, nginx, used for what?
- Spring boot - disable Liquibase at startup
- Spring Boot - enable and configure SSL certificate
- Spring Boot - Error creating bean with name 'dataSource' defined in class path resource
- Spring Boot - Handle to Hibernate SessionFactory
- Spring Boot - how to communicate between microservices?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseData Structures & Algorithms practice on Codemia
Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.