Spring Boot
static content
404 error
jar file
troubleshooting

Spring Boot project with static content generates 404 when running jar

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A Spring Boot application may serve static assets correctly in development but return 404 when packaged as an executable jar. The root cause is usually resource placement, packaging configuration, or URL mapping conflicts. A repeatable diagnostic workflow can resolve this quickly.

Core Sections

Where Spring Boot Looks for Static Resources

By default, Spring Boot serves static content from classpath locations such as static, public, and META-INF/resources. The common path for web assets is:

  • src/main/resources/static

If files are placed under src/main/webapp, behavior can differ depending on packaging mode and build setup. For jar packaging, classpath resource directories are the safest default.

Confirm Assets Are Packaged into the Jar

Before changing code, inspect the built artifact and verify assets exist where runtime expects them.

bash
./mvnw clean package
jar tf target/myapp-0.0.1-SNAPSHOT.jar | rg 'static|index.html|css|js'

For Gradle:

bash
./gradlew clean bootJar
jar tf build/libs/myapp-0.0.1-SNAPSHOT.jar | rg 'static|index.html|css|js'

If files are missing, check build excludes, incorrect source directories, or accidental profile-specific filtering.

Correct Project Layout and Access Paths

A minimal layout that works reliably:

text
src/main/resources/static/index.html
src/main/resources/static/css/app.css
src/main/resources/static/js/app.js

Then run the jar and test with direct URLs.

bash
java -jar target/myapp-0.0.1-SNAPSHOT.jar
curl -I http://localhost:8080/
curl -I http://localhost:8080/css/app.css

If your app uses server.servlet.context-path=/app, static resources move under that prefix, so the URL becomes /app/css/app.css.

Avoid Controller Mapping Collisions

A broad controller mapping can steal requests from static resource handlers.

java
1@Controller
2public class HomeController {
3
4    @GetMapping("/")
5    public String home() {
6        return "home";
7    }
8}

If this returns a view name that does not exist, you may see 404 and assume static mapping failed. Keep API routes under /api and let static paths remain unmapped unless customization is intentional.

Explicit Resource Handler Configuration

When custom behavior is needed, configure resource handlers directly.

java
1@Configuration
2public class WebConfig implements WebMvcConfigurer {
3
4    @Override
5    public void addResourceHandlers(ResourceHandlerRegistry registry) {
6        registry.addResourceHandler("/assets/**")
7                .addResourceLocations("classpath:/static/");
8    }
9}

This is useful when migrating legacy URLs or serving assets under a custom prefix. Verify that rewritten paths in frontend HTML match this mapping.

Troubleshoot Jar Runtime Versus IDE Runtime

IDE launches may include directories that differ from final jar classpath. Always validate with the actual packaged jar.

bash
java -jar target/myapp-0.0.1-SNAPSHOT.jar --debug

Debug output helps confirm handler mappings and active profiles. If profiles alter static path properties, a jar started without expected profile can produce a false 404 signal.

SPA Fallback Strategy

For single-page applications, direct navigation to a frontend route may return 404 unless fallback routing is configured. Add a controller that forwards unknown non-file routes to index.html.

java
1@Controller
2public class SpaForwardController {
3
4    @GetMapping("/{path:[^\\.]*}")
5    public String redirect() {
6        return "forward:/index.html";
7    }
8}

This keeps API routes separate while allowing client-side routing frameworks to own route resolution.

Verify Resource Caching and MIME Types

A response can still appear broken even when files are found, especially if MIME type or cache headers are incorrect. Verify static responses directly at runtime.

bash
curl -I http://localhost:8080/js/app.js
curl -I http://localhost:8080/css/app.css

Expect 200 and correct content types such as application/javascript and text/css. Also confirm cache policy aligns with release strategy, especially if file names are fingerprinted. Correct packaging plus proper headers prevents both 404 issues and stale frontend assets after deployment.

Common Pitfalls

  • Storing static files outside classpath resource directories for jar builds.
  • Verifying only IDE runtime and not checking packaged jar contents.
  • Forgetting context-path prefixes when testing static URLs.
  • Using broad controller mappings that intercept static resource requests.
  • Enabling SPA routes without a server-side fallback to index.html.

Summary

  • Put static files under src/main/resources/static for reliable jar serving.
  • Inspect built jar contents before debugging application code.
  • Validate URLs with context-path and profile settings applied.
  • Keep controller mappings from colliding with static handlers.
  • Add explicit resource handlers or SPA fallback only when needed.

Course illustration
Course illustration

All Rights Reserved.