keepcalculator

06 Numbers and Powers

Spring Boot Request Path: Tomcat to Controller

Card No. 06·19722 · Updated · Standard formula, shown below

This guide explains the exact journey of an HTTP request in a Spring Boot application, from the moment it hits the embedded Tomcat server until it reaches your controller method. You’ll learn the key components involved, the order of processing, and how to debug issues when a request doesn’t arrive as expected.

What You’ll Need

  • A Spring Boot application (version 2.x or 3.x) with at least one REST controller.
  • Basic knowledge of Spring annotations like @RestController, @RequestMapping, and @GetMapping.
  • An HTTP client (e.g., Postman, curl, or a browser) to send requests.
  • Access to the application logs (console or log file) for troubleshooting.

Step-by-Step

  1. Start the application. Run your Spring Boot app. By default, it starts an embedded Tomcat server on port 8080. The server listens for incoming TCP connections on that port.
  2. Send an HTTP request. Use your client to send a request, for example GET http://localhost:8080/api/users. This creates a TCP connection to the Tomcat connector.
  3. Tomcat accepts the connection. The Tomcat connector (usually Http11NioProtocol) accepts the TCP connection and hands it to an executor thread. Tomcat maintains a thread pool to handle concurrent requests.
  4. Tomcat parses the HTTP request. The connector reads the raw bytes and parses them into an HttpServletRequest object. This includes the request line (method, URI, protocol), headers, and body (if any).
  5. Tomcat passes the request to the Engine. The connector forwards the request to the Tomcat Engine, which is the top-level container. The Engine’s pipeline includes several valves (e.g., access log, remote host filter). These valves can modify or reject the request.
  6. The Engine selects a Host. The Engine chooses a Host (usually localhost) based on the request’s Host header. The Host’s pipeline processes the request further.
  7. The Host selects a Context. The Host maps the request to a Context (your Spring Boot application). This is done by matching the context path (usually empty or /).
  8. The Context’s wrapper handles the request. The Context contains one or more Wrappers, each representing a servlet. For Spring Boot, there is a single DispatcherServlet mapped to /. The Context passes the request to that wrapper.
  9. DispatcherServlet receives the request. The DispatcherServlet is the front controller for Spring MVC. Its doDispatch method orchestrates the entire request handling process.
  10. Handler mapping. The servlet asks all registered HandlerMapping beans to find a handler for the request. The most common is RequestMappingHandlerMapping, which matches the request path and method against your controller’s annotations. It returns a HandlerExecutionChain containing the handler method and any interceptors.
  11. Handler adapters. The servlet finds a HandlerAdapter that supports the selected handler. For annotated controllers, it uses RequestMappingHandlerAdapter. This adapter is responsible for invoking the handler method.
  12. Interceptors preHandle. Before the handler runs, each registered HandlerInterceptor‘s preHandle method is called. If any returns false, the chain stops and the request is not processed further.
  13. Argument resolution. The adapter resolves method arguments. For example, if your controller method has @PathVariable Long id, it extracts the value from the URI. It also handles @RequestBody by converting the request body using an HttpMessageConverter (e.g., Jackson for JSON).
  14. Controller method invocation. The adapter invokes your controller method. This is the code you wrote – it executes and returns a value (e.g., a ResponseEntity or a POJO).
  15. Return value handling. The adapter processes the return value. If it’s a POJO, it uses a HttpMessageConverter to serialize it to JSON (or XML). If it’s a ResponseEntity, it uses the status and headers from that object.
  16. Interceptors postHandle. After the handler returns, each interceptor’s postHandle method is called. It can modify the ModelAndView (if any).
  17. Exception resolution. If any exception was thrown during processing, the DispatcherServlet delegates to HandlerExceptionResolver beans. The default ExceptionHandlerExceptionResolver handles exceptions annotated with @ExceptionHandler or @ControllerAdvice.
  18. Response rendering. The servlet writes the response to the HttpServletResponse. This includes setting status code, headers, and writing the body.
  19. Tomcat sends the response. The response travels back down the container hierarchy. The connector writes the bytes to the client over the TCP connection.
  20. Request thread returns. The executor thread is released back to the pool, ready for the next request.

Common Mistakes

  • Wrong context path. If your application has server.servlet.context-path=/api, you must include that prefix in your request URL. A request to /users will 404.
  • Missing dependencies. Forgetting to include Spring Web (e.g., spring-boot-starter-web) results in a plain Tomcat server with no DispatcherServlet, so all requests return 404 or 405.
  • Incorrect HTTP method. Using @GetMapping but sending a POST request results in 405 Method Not Allowed.
  • Path variable mismatch. If your mapping is @GetMapping("/users/{id}") and you request /users, you get 404. The path must match exactly.
  • Not handling exceptions. Unhandled exceptions result in a generic 500 error with a stack trace in the logs, but no useful response to the client.

Tips

  • Enable debug logging. Set logging.level.org.springframework.web=DEBUG in application.properties to see detailed request mapping and handler execution logs.
  • Use a global exception handler. Create a @ControllerAdvice class with @ExceptionHandler methods to return consistent error responses.
  • Understand interceptors. Interceptors are great for cross-cutting concerns like logging or authentication. Remember they run before and after the controller method.
  • Test with curl. Use curl -v http://localhost:8080/api/users to see the full request/response cycle including headers and status codes.
  • Know your servlet container. Spring Boot can use Tomcat, Jetty, or Undertow. The request path is similar, but the connector details differ.

Troubleshooting

Request returns 404. Check the URL path and context path. Verify that the controller is annotated with @RestController or @Controller and that the mapping matches. Look for typos in the path.

Request returns 405. The path exists but the HTTP method is wrong. Check the mapping annotation (@GetMapping, @PostMapping, etc.).

Request returns 500. An exception occurred. Check the application logs for the stack trace. Common causes: null pointer, serialization error, or database failure.

Request never reaches the controller. Check if any interceptor’s preHandle returns false. Also check if a filter (e.g., Spring Security) is blocking the request.

Slow response. The bottleneck might be in the controller logic, database queries, or external API calls. Use profiling tools or add logging around the method to measure time.

Frequently Asked Questions

What is the DispatcherServlet?

It’s the front controller in Spring MVC that receives all HTTP requests and delegates to handler methods. It’s responsible for request mapping, argument resolution, and response handling.

How does Spring Boot choose Tomcat as the default server?

Spring Boot’s spring-boot-starter-web includes Tomcat as the default embedded server. You can exclude it and add Jetty or Undertow if you prefer.

Can I change the port Tomcat listens on?

Yes, set server.port=8081 in application.properties or use the --server.port command-line argument.

What is the difference between a filter and an interceptor?

Filters are part of the servlet specification and run before the DispatcherServlet. Interceptors are Spring MVC components that run within the DispatcherServlet’s processing, before and after controller methods.

Why is my request body null in the controller?

Make sure you have @RequestBody on the parameter and that the request’s Content-Type header is set to application/json (or XML). Also ensure the body is not empty.

How can I see the exact request mapping that was matched?

Enable debug logging for org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping to see which handler is selected for each request.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →