Day 9 · 1 Hour
REST API Advanced
Validation, error handling, pagination — APIs that work like a senior developer wrote them.
🔥 Real-World Hook (0–5 min)
Every time you open Swiggy, 15 different APIs fire in parallel: auth check, restaurant list, your cart, promotions, location, payment methods.
Each one returns JSON. Each one is secured. Each one handles errors gracefully. Today you build APIs like a senior developer — validation, error handling, pagination, and security.
🔒 Professional REST API Design (5–20 min)
💡 Rules of Good APIs
✔ Use nouns for resources: /students not /getStudents
✔ Use HTTP verbs for actions: GET=read, POST=create, PUT=update, DELETE=remove
✔ Return proper status codes: 200=OK, 201=Created, 404=Not Found, 400=Bad Request
✔ Validate input: never trust the client
✔ Return consistent error format
💻 Live Coding — Production-Grade API (20–40 min)
// DTO — only expose what clients need public record StudentRequest( @NotBlank String name, @Email String email, @Min(1) @Max(4) int year ) {} // Global exception handler @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<ErrorResponse> handleNotFound(Exception ex) { return ResponseEntity.status(404) .body(new ErrorResponse("NOT_FOUND", ex.getMessage())); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) { String msg = ex.getBindingResult().getFieldErrors().stream() .map(e -> e.getField() + ": " + e.getDefaultMessage()) .collect(Collectors.joining(", ")); return ResponseEntity.badRequest().body(new ErrorResponse("VALIDATION_ERROR", msg)); } } // Paginated endpoint @GetMapping public Page<Student> getAll( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { return repo.findAll(PageRequest.of(page, size)); }
🎯 You Code It (40–55 min)
- Add
spring-boot-starter-validationto your pom.xml - Create a
ProductRequestDTO with:@NotBlank name,@Positive price,@NotBlank category - Add
@Validto your POST endpoint's@RequestBodyparameter - Create a
GlobalExceptionHandlerclass that returns JSON error messages - Test: POST with an empty name field — should return 400 with error message
- Add pagination to GET all products:
?page=0&size=5
📄 Day 9 Cheat Sheet — REST API
Validation Annotations
| @NotBlank | Not null & not empty |
| @NotNull | Not null |
| Valid email format | |
| @Min(n) @Max(n) | Number range |
| @Size(min=2,max=50) | String length |
| @Positive | Greater than 0 |
HTTP Status Codes
| 200 OK | Success |
| 201 Created | Resource created |
| 204 No Content | Deleted / empty |
| 400 Bad Request | Invalid input |
| 404 Not Found | Resource missing |
| 500 Server Error | Unexpected crash |
Exception Handling
| @RestControllerAdvice | Global handler |
| @ExceptionHandler(Ex.class) | Handle specific |
| ResponseEntity.badRequest() | 400 response |
| ResponseEntity.status(404) | 404 response |
| ex.getMessage() | Error text |
Pagination
| extends JpaRepository | Already has it |
| PageRequest.of(page, size) | Create pageable |
| Page<T> findAll(Pageable p) | Get page |
| page.getTotalElements() | Total count |
| page.getTotalPages() | Total pages |
| ?page=0&size=10 | Query params |