Skip to main content

๐Ÿง  What REALLY Happens When You Hit a Spring Boot REST API?

๐Ÿง  What REALLY Happens When You Hit a Spring Boot REST API?

๐Ÿ’ฅ Inside the Hidden World of Filters, Interceptors & DispatcherServlet


๐ŸŽฌ Intro: “It’s Just a Simple API Call…” — Said Every Developer Before Debugging It

You hit this:

GET http://localhost:8080/api/user/42

๐ŸŽฏ And your controller returns the user info. Done, right?

๐Ÿ˜ LOL no.

Welcome to Spring Boot, where your request goes on a rollercoaster ride through filters, interceptors, servlet containers, exception resolvers, and more — before it even thinks about reaching your controller.

Let’s deep-dive into the secret life of a REST API call in Spring Boot — with ๐Ÿ” internal mechanics, ๐Ÿ˜ฑ common mistakes


⚙️ 1. ๐Ÿšช The Request Arrives at... The Bouncer (Tomcat)

Spring Boot has an embedded server (usually Tomcat). When your app starts, it's like opening a door at a nightclub. The request knocks. ๐Ÿ•บ

Tomcat says:
"Who dis? ๐Ÿคจ"
And then it lets the HTTP request enter.

๐Ÿง  Technically: Tomcat parses the socket connection and sends the request into the Servlet layer.


๐Ÿงฐ 2. ๐Ÿš“ Filters Step In – “We Check Everyone!”

@Component
public class MyFilter implements Filter {
    public void doFilter(...) {
        // CORS? Auth header? Logging? All here
        chain.doFilter(request, response);
    }
}

๐Ÿ” What They Do:

  • Logging ๐Ÿชต
  • Header checks ๐Ÿงพ
  • CORS setup ๐ŸŒ
  • JWT parsing ๐Ÿ”

⚠️ Can’t access Spring beans easily (they live in the servlet world ๐ŸŒ).

Joke:
“Filters are like your mom at the door. If your hair’s messy or token is missing, she won’t let you go to the party.” ๐Ÿ˜†

๐Ÿง  3. ๐ŸŽฉ Enter the DispatcherServlet — The Real Boss

Spring's legendary DispatcherServlet is the Front Controller.

It’s the guy in the suit standing behind the scenes, pointing where every request should go.

@Bean
public DispatcherServlet dispatcherServlet() {
    return new DispatcherServlet();
}

๐Ÿงญ Responsibilities:

  • Picks the right controller ๐Ÿค–
  • Handles exceptions ๐Ÿ’ฅ
  • Sends responses ๐Ÿ’Œ
  • Makes sure your REST endpoint actually gets called

๐Ÿšฆ 4. ๐Ÿ•ต️ Interceptors Arrive – “We See What You Do”

Unlike filters, interceptors live in Springland, where you get DI, beans, and control. ๐Ÿ˜Ž

@Component
public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(...) { }
    public void postHandle(...) { }
    public void afterCompletion(...) { }
}

preHandle() — Before Controller

  • Block request? Return false. ๐Ÿšซ
  • Start timing? ⏱️
  • Check session? ๐Ÿ”‘

๐Ÿ”„ postHandle() — After Controller

  • Modify ModelAndView ๐ŸŽญ
  • Log what controller returned ✅
  • Inject extra data before view is rendered ๐ŸŒˆ

๐Ÿšซ You can't modify the JSON response here if it’s a REST controller.

๐Ÿ”š afterCompletion() — After Response Sent

  • Log request duration ⏱️
  • Cleanup (ThreadLocal, MDC) ๐Ÿงน
  • Log exceptions ๐Ÿค•

You cannot modify the response here; it’s already committed!


๐ŸŽฏ 5. ๐ŸŽฏ Handler Mapping – “Where’s This Request Supposed to Go?”

Spring finds the matching controller based on:

  • URL path ๐Ÿ›ฃ️
  • HTTP method ๐Ÿ”„
  • Annotations like @GetMapping, @PostMapping
@GetMapping("/api/user/{id}")
public User getUser(@PathVariable Long id) {
    return userService.findUser(id);
}

๐Ÿค– 6. Your Controller Finally Runs ๐ŸŽ‰

Spring injects everything you love:

  • @PathVariable, @RequestParam, @RequestBody
  • Autowired beans
  • RequestContext, Headers, etc.

๐Ÿ’ฃ 7. Boom! Exceptions? Enter @ControllerAdvice ๐Ÿ’ฌ

@ControllerAdvice
public class MyErrorHandler {
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<?> handleIt() {
        return ResponseEntity.status(404).body("No user, bro!");
    }
}

✅ Spring checks for matching exception handlers.
❌ If none are found → you get a white-label error page (uglyyyy).


๐Ÿ“ค 8. Response Goes Back (Backwards Flow)

The response now goes through:

  1. ResponseBodyAdvice ๐Ÿ› ️
  2. Interceptors: postHandle()afterCompletion() ๐Ÿ”„
  3. Servlet Filters (again) ๐Ÿšฆ
  4. Embedded server (Tomcat) ✉️
  5. The client gets the final response ๐ŸŽ‰

๐Ÿ—บ️ The Full Lifecycle Map


Client
 ↓
๐ŸŒ Embedded Server (Tomcat)
 ↓
๐Ÿš“ Filters (Servlet API)
 ↓
๐ŸŽฉ DispatcherServlet
 ↓
๐Ÿ•ต️ Interceptor.preHandle()
 ↓
๐Ÿงญ Handler Mapping
 ↓
๐ŸŽฏ Controller Logic
 ↓
๐Ÿงน Interceptor.postHandle()
 ↓
๐Ÿ“ฆ ResponseBodyAdvice
 ↓
๐Ÿงผ Interceptor.afterCompletion()
 ↓
๐Ÿ›‚ Filters (post)
 ↓
✉️ Response to Client

๐ŸŽฏ Should I Set Headers in a Filter or an Interceptor? ๐Ÿค”

Great question! You might be wondering:

“If I can add headers in a filter, why should I ever use an interceptor?” ๐Ÿคจ

๐Ÿ› ️ Short Answer:

✅ Both can add headers.
๐Ÿšซ But filters don’t know which controller is being called.
๐Ÿ’ก Interceptors do, and they have full Spring context.


๐Ÿ”ฌ Case Studies to Compare

1️⃣ Global Headers — Use a Filter ✅

// Filter example
response.setHeader("X-App-Version", "1.0.9");
response.setHeader("X-Frame-Options", "DENY");

Perfect for:

  • CORS headers ๐ŸŒ
  • Security headers ๐Ÿ”
  • Trace IDs ๐Ÿงต

2️⃣ Controller-Specific Headers — Use an Interceptor ๐Ÿ’ก

// Interceptor example
public void postHandle(...) {
  if (handler instanceof HandlerMethod hm &&
      hm.hasMethodAnnotation(MySpecialHeader.class)) {
      response.setHeader("X-Special", "true");
  }
}

Interceptors know:

  • Which controller method is running ๐Ÿง 
  • What annotations are present ๐Ÿ”
  • Can access Spring beans! ๐ŸŒฑ

3️⃣ Modify Headers After Controller — Use Interceptor or ResponseBodyAdvice ๐Ÿ”

If your controller is REST and you need to add headers *after* business logic:

  • ✅ Interceptor’s postHandle() (for headers)
  • ResponseBodyAdvice (for body + headers๐Ÿ’ฌ Interviewer May Ask:
“Can you set headers in a filter?” ✅ Yes, but only generic ones.
“Can you modify headers based on the controller?” ❌ Not in filters. ✅ Use interceptors!

๐ŸŽฏ Rule of Thumb:

  • Use filters when you need to do something BEFORE Spring kicks in
  • Use interceptors when you want access to Spring context, beans, and controller logic

๐ŸŽ Bonus Tip:

For REST APIs, add metadata headers like:

response.setHeader("X-Request-ID", requestId);
response.setHeader("X-User-ID", userId);

This helps in:

  • ๐ŸŒ Distributed tracing
  • ๐Ÿ” Debugging logs across microservices
  • ๐Ÿ“ˆ Monitoring APIs under load

๐Ÿ’ฌ What About You?

Ever confused filters and interceptors in a live project or interview? ๐Ÿ˜… Did someone add response headers in afterCompletion() and wonder why they didn't show up?

Share your war stories in the comments below ๐Ÿ‘‡

๐Ÿงช Interview Questions You’ll Crush After Reading This

❓ Question ✅ Answer
Filter vs Interceptor? Filter = Servlet level
Interceptor = Spring MVC level
Can I block request in preHandle()? Yes, return false to stop the flow
Can I modify response in afterCompletion()? ❌ No. Response already committed
Where to log time taken? afterCompletion() is ideal ⏱️
Filter throws exception. Who handles it? Global exception handler won’t catch unless inside Spring context

๐Ÿช„ Wrapping Up: You Just Became a Request Flow Wizard ๐Ÿง™

Most devs debug controller issues without knowing filters or interceptors even touched the request.
But not you. ๐Ÿ’ช You now know exactly who does what, when, and why.

Whether it’s logging, security, tracing, or performance — this internal flow gives you superpowers in both interviews and real projects.

๐Ÿ’ฌ Your Turn:

Ever spent hours debugging a request that mysteriously vanished? Was it a filter, a missing header, or a short-circuiting preHandle()? ๐Ÿ˜… Drop your war stories in the comments ๐Ÿ‘‡


Comments

Popular posts from this blog

๐Ÿ” Is final Really Final in Java? The Truth May Surprise You ๐Ÿ˜ฒ

๐Ÿ’ฌ “When I was exploring what to do and what not to do in Java, one small keyword caught my eye — final . I thought it meant: locked, sealed, frozen — like my fridge when I forget to defrost it.”   But guess what? Java has its own meaning of final… and it’s not always what you expect! ๐Ÿ˜… Let’s break it down together — with code, questions, confusion, jokes, and everything in between. ๐ŸŽฏ The Confusing Case: You Said It's Final... Then It Changed?! ๐Ÿซ  final List<String> names = new ArrayList <>(); names.add( "Anand" ); names.add( "Rahul" ); System.out.println(names); // [Anand, Rahul] ๐Ÿคฏ Hold on... that’s final , right?! So how on earth is it still changing ? Time to dive deeper... ๐Ÿง  Why Is It Designed Like This? Here’s the key secret: In Java, final applies to the reference , not the object it points to . Let’s decode this like a spy mission ๐Ÿ•ต️‍♂️: Imagine This: final List<String> names = new ArrayList <>(); Be...

๐ŸŒŸ My Journey – From Zero to Senior Java Tech Lead ๐ŸŒŸ

 There’s one thing I truly believe… If I can become a Java developer, then anyone in the world can. ๐Ÿ’ฏ Sounds crazy? Let me take you back. ๐Ÿ•“ Back in 2015… I had zero coding knowledge . Not just that — I had no interest in coding either. But life has its own plans. In 2016, I got a chance to move to Bangalore and joined a Java course at a training center. That’s where it all started — Every day, every session made me feel like: "Ohhh! Even I can be a developer!" That course didn’t just teach Java — it gave me confidence . ๐Ÿงช Two Life-Changing Incidents 1️⃣ The Interview That Wasn't Planned Halfway through my course, I had to urgently travel to Chennai to donate blood to a family member. After that emotional rollercoaster, I found myself reflecting on my skills and the future. The next day, as I was preparing for my move to Bangalore to complete the remaining four months of my course, I randomly thought — "Let me test my skills... let me just see...

๐ŸŽข Java Loops: Fun, Fear, and ForEach() Fails

๐ŸŒ€ Oops, I Looped It Again! — The Ultimate Java Loop Guide You Won't Forget “I remember this question from one of my early interviews — I was just 2 years into Java and the interviewer asked, ‘Which loop do you prefer and why?’” At first, I thought, “Duh! for-each is cleaner.” But then he grilled me with cases where it fails. ๐Ÿ˜ต That led me to explore all loop types, their powers, and their pitfalls. Let’s deep-dive into every major Java loop with examples &  real-world guidance so you'll never forget again. ๐Ÿ” Loop Type #1: Classic For Loop — “The Old Reliable” ✅ When to Use: You need an index You want to iterate in reverse You want full control over loop mechanics ✅ Good Example: List<String> names = List.of("A", "B", "C"); for (int i = 0; i < names.size(); i++) { System.out.println(i + ": " + names.get(i)); } ๐Ÿ”ฅ Reverse + Removal Example: List<String> item...