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...

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?
server:
servlet:
context-path: /api/v1
/users endpoint will actually be served at:👉 http://localhost:8080/api/v1/users
/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
/users but your service expects /api/v1/users, the request will never reach the controller.
/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
server:
port: 8080
servlet:
context-path: /luz-docs
/luz-docs/....
2.2 Programmatic Configuration (for dynamic context paths)
@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);
}
}
2.3 Common Pitfall: Forgetting the Trailing Slash
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.
3. Logging 404 Errors Separately
3.1 Why You Should Separate 404 Logs
- 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
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";
}
}
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>
logs/404.log, leaving your main logs free from noise.
4. Testing and Observing 404 Behavior
4.1 Example Request Flow
Access a valid endpoint:
GET http://localhost:8080/luz-docs/api/v1/users→ Logged to
application.logAccess an invalid one:
GET http://localhost:8080/luz-docs/api/v1/ghost→ Logged to
logs/404.log
4.2 Bonus: 404 Metrics
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();
}
}
CustomErrorController—and voilà, now you can alert on spikes of 404s.
5. Practical Tips and Common Gotchas
- Always verify your
context-pathconsistency between your application.yml and gateway routing. - Do not use
@RestControllerAdvicefor 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
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.
Read more at : Techniques to Configure server.servlet.context-path and Log 404 Errors Separately in Spring Boot





