Skip to main content

Command Palette

Search for a command to run...

Techniques to Configure server.servlet.context-path and Log 404 Errors Separately in Spring Boot

When working with complex microservices or multi-tenant systems, a small detail like the context-path can make a big difference in routing, logging, and debugging your API. Yet, developers often overlook how this setting affects error handling—es...

Published
5 min read
Techniques to Configure server.servlet.context-path and Log 404 Errors Separately in Spring Boot
T

I am Tuanh.net. As of 2024, I have accumulated 8 years of experience in backend programming. I am delighted to connect and share my knowledge with everyone.

1. Understanding server/servlet/context-path

1.1 What is a Context Path?

In Spring Boot, the context path defines the base URI under which all your application’s endpoints are served.For example, if you set:

server:
servlet:
context-path: /api/v1

Then your controller’s /users endpoint will actually be served at:👉 http://localhost:8080/api/v1/users

Without this prefix, it would simply be /users.It’s like the “root directory” of your web app—useful when deploying multiple applications under the same domain.

1.2 Why You Should Care About It

A misconfigured context path can lead to 404 errors, broken reverse proxies, or routing confusion between microservices. For instance, if your gateway forwards requests to /users but your service expects /api/v1/users, the request will never reach the controller.

When you scale your system across environments—/dev, /staging, /prod—the context path can help isolate traffic and make your deployment structure predictable.

2. Setting and Using the Context Path in Spring Boot

2.1 Configuration via application.yml

This is the most straightforward approach:

server:
port: 8080
servlet:
context-path: /luz-docs

After this, your endpoints will live under /luz-docs/....

2.2 Programmatic Configuration (for dynamic context paths)

Sometimes you may want the path to depend on environment variables:

@SpringBootApplication
public class LuzDocsApplication {

public static void main(String[] args) {
SpringApplication app = new SpringApplication(LuzDocsApplication.class);
app.addListeners((ApplicationEnvironmentPreparedEvent event) -> {
String tenant = System.getenv("TENANT_ID");
if (tenant != null) {
event.getEnvironment()
.getSystemProperties()
.put("server.servlet.context-path", "/" + tenant);
}
});
app.run(args);
}
}

This approach dynamically sets the context path per tenant or per environment—handy in multi-tenant microservices like luz-docs or luz-jsonstore.

2.3 Common Pitfall: Forgetting the Trailing Slash

Setting server.servlet.context-path: /api vs /api/ seems trivial but can break request mappings, depending on how your gateway or proxy rewrites paths.Always make sure your reverse proxy (Nginx, Spring Cloud Gateway, etc.) aligns perfectly with the configured context path.

A good rule of thumb:

3. Logging 404 Errors Separately

3.1 Why You Should Separate 404 Logs

In large systems, 404s often come from frontend misroutes, health checks, or random crawlers. Mixing them with real server errors makes your logs noisy and hides real problems.

Separating 404s helps you:

  • Detect missing routes quickly.
  • Monitor API usage patterns (what endpoints users are trying to reach).
  • Reduce alert fatigue in centralized log systems (e.g., Grafana, ELK, Cloud Logging).

3.2 Implementing Custom 404 Logging

Spring Boot allows you to handle all unmapped URLs using a custom ErrorController.Here’s a clean example:

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CustomErrorController implements ErrorController {

private static final Logger log404 = LoggerFactory.getLogger("404_LOGGER");

@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
Object uri = request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);

if (status != null && Integer.parseInt(status.toString()) == HttpStatus.NOT_FOUND.value()) {
log404.warn("404 Not Found: {}", uri);
}
return "forward:/static/404.html";
}
}

Now, to route these 404 logs to a separate file, define a custom logger in logback-spring.xml:

<configuration>
<appender name="FILE_404">
<file>logs/404.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %msg%n</pattern>
</encoder>
<rollingpolicy>
<filenamepattern>logs/404.%d{yyyy-MM-dd}.log</filenamepattern>
</rollingpolicy>
</appender>

<logger name="404_LOGGER" level="WARN" additivity="false">
<appender-ref ref="FILE_404">
</appender-ref></logger>
</configuration>

🎯 Now all your 404s go neatly into logs/404.log, leaving your main logs free from noise.

4. Testing and Observing 404 Behavior

4.1 Example Request Flow

  1. Access a valid endpoint:

    GET http://localhost:8080/luz-docs/api/v1/users

    → Logged to application.log

  2. Access an invalid one:

    GET http://localhost:8080/luz-docs/api/v1/ghost

    → Logged to logs/404.log

4.2 Bonus: 404 Metrics

You can even expose 404 count metrics for Grafana or Prometheus:

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;

@Component
public class NotFoundMetrics {

private final MeterRegistry registry;

public NotFoundMetrics(MeterRegistry registry) {
this.registry = registry;
}

public void count404(String uri) {
registry.counter("http.404.count", "uri", uri).increment();
}
}

Integrate it inside the CustomErrorController—and voilà, now you can alert on spikes of 404s.

5. Practical Tips and Common Gotchas

  • Always verify your context-path consistency between your application.yml and gateway routing.
  • Do not use @RestControllerAdvice for 404 logging—it only captures exceptions, not unmapped URLs.
  • Use separate appenders for different log types (e.g., 404, security, SQL) to enhance visibility.
  • Test both with and without trailing slashes in your gateway routes.

6. Conclusion

Setting the correct server.servlet.context-path might look simple, but it’s foundational for consistent routing across services. When combined with 404-separated logging, it transforms debugging into a clean, predictable process.

If you’ve ever wondered why your Spring Boot logs are messy or why some URLs vanish into 404 oblivion, this setup will feel like turning on the lights in a dark server room.

💬 Have questions about configuring context-paths dynamically or logging other HTTP statuses separately?

Drop your question below — let’s debug smarter, not harder.

Read more at : Techniques to Configure server.servlet.context-path and Log 404 Errors Separately in Spring Boot

More from this blog

T

tuanh.net

540 posts

Are you ready to elevate your Java, OOP, Spring, and DevOps skills? Look no further!