Web MVC, REST, Validation & Errors

Overview

How an HTTP request becomes a Java method call, how Spring reads/writes JSON, how @Valid rejects bad input, and how @ControllerAdvice centralises error responses.

Official: Spring MVC.


Table of contents

  1. Request lifecycle
  2. @RestController vs @Controller
  3. Mapping URLs to methods
  4. JSON in and out
  5. Validation with @Valid
  6. Global exception handling
  7. ProblemDetail (Spring 6)
  8. Interview questions
  9. Summary

1. Request lifecycle

  1. Embedded Tomcat receives the HTTP request.
  2. Spring’s DispatcherServlet finds the matching controller method by path + verb.
  3. Spring binds path variables, query params, headers, body into method parameters.
  4. The method runs and returns a value.
  5. For @RestController, Spring serialises the return value to JSON (default via Jackson) and sets Content-Type: application/json.

2. @RestController vs @Controller

Annotation Returns Spring does
@Controller View name ("home") Renders a template
@RestController An object (DTO, record, list) Serialises to JSON

@RestController is literally @Controller + @ResponseBody on every method.


3. Mapping URLs to methods

@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @GetMapping("/{id}")
    public Order get(@PathVariable Long id) { ... }

    @GetMapping
    public List<Order> list(@RequestParam(required = false) String status) { ... }

    @PostMapping
    public ResponseEntity<Order> create(@Valid @RequestBody CreateOrderRequest body) {
        Order saved = service.create(body);
        return ResponseEntity
            .created(URI.create("/api/orders/" + saved.getId()))
            .body(saved);
    }
}
Annotation Source
@PathVariable URL segment (/orders/42)
@RequestParam Query string (?status=OPEN)
@RequestHeader HTTP headers
@RequestBody JSON request body

@GetMapping / @PostMapping are shortcuts for @RequestMapping(method = ...).


4. JSON in and out

  • Incoming JSON → Java: @RequestBody on the parameter; Jackson deserialises.
  • Outgoing Java → JSON: return any POJO/record; Jackson serialises.

Use ResponseEntity when you need to control HTTP status or headers (e.g. 201 Created with a Location header).


5. Validation with @Valid

  1. Put Bean Validation annotations on the DTO:
public record CreateOrderRequest(
    @NotBlank String customerId,
    @Positive int quantity
) {}
  1. Add @Valid to the controller parameter:
@PostMapping
public Order create(@Valid @RequestBody CreateOrderRequest req) { ... }
  1. If invalid, Spring throws MethodArgumentNotValidException before your method runs.

@Validated (Spring’s version) adds validation groups — only needed for advanced cases.


6. Global exception handling

Instead of try/catch in every controller, declare a @RestControllerAdvice:

@RestControllerAdvice
public class ApiExceptionHandler {

    @ExceptionHandler(NotFoundException.class)
    public ResponseEntity<ProblemDetail> notFound(NotFoundException e) {
        var pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(pd);
    }
}

One handler, consistent error shape across the whole API.


7. ProblemDetail (Spring 6)

ProblemDetail is Spring’s built-in implementation of RFC 7807 (application/problem+json):

Field Meaning
type URI identifying the error class
title Short human title
status HTTP status
detail Specific explanation
instance Unique id for this occurrence

Stable shape → clients and gateways handle errors uniformly.


8. Interview questions

Q: @RestController vs @Controller? A: @RestController adds @ResponseBody so return values are written to the response body (usually JSON). @Controller is for server-rendered HTML.

Q: What does @Valid do? A: Runs Bean Validation on the object; invalid input throws MethodArgumentNotValidException before the handler runs.

Q: What is @RestControllerAdvice? A: A global bean holding @ExceptionHandler methods that apply to every controller.

Q: How do I return 201 Created with a Location header? A: ResponseEntity.created(URI).body(...).

Q: What is ProblemDetail? A: Spring 6’s Java type for RFC 7807 problem+json error responses.


9. Summary

Piece Role
@RestController JSON in/out
@RequestBody / return type Jackson serialisation
@Valid Input validation
@RestControllerAdvice Central error handling
ProblemDetail RFC 7807 error body

Next steps


Happy Learning

Next: Data Access (JPA) & Transactions