Handling not found exceptions helps your app respond clearly when something is missing. It avoids crashes and tells users what went wrong.
Handling not found exceptions in Spring Boot
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } }
Use @ResponseStatus(HttpStatus.NOT_FOUND) to set the HTTP status code to 404.
Extend RuntimeException to create a custom unchecked exception.
public class UserNotFoundException extends RuntimeException { public UserNotFoundException(String message) { super(message); } }
@ResponseStatus(HttpStatus.NOT_FOUND) public class UserNotFoundException extends RuntimeException { public UserNotFoundException(String message) { super(message); } }
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); } }
This Spring Boot app has a simple user map. When you ask for a user by ID, it returns the name if found. If not, it throws UserNotFoundException. The exception handler sends a 404 status with a clear message.
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @SpringBootApplication @RestController public class DemoApplication { private Map<Integer, String> users = new ConcurrentHashMap<>(); public DemoApplication() { users.put(1, "Alice"); users.put(2, "Bob"); } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @GetMapping("/users/{id}") public String getUser(@PathVariable int id) { String user = users.get(id); if (user == null) { throw new UserNotFoundException("User with id " + id + " not found."); } return user; } @ResponseStatus(HttpStatus.NOT_FOUND) static class UserNotFoundException extends RuntimeException { public UserNotFoundException(String message) { super(message); } } @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); } }
Always provide a clear message in your exception to help users and developers understand the problem.
Use @ControllerAdvice for global exception handling across all controllers.
Returning proper HTTP status codes improves API usability and debugging.
Custom exceptions help handle missing resources cleanly.
Use @ResponseStatus(HttpStatus.NOT_FOUND) or exception handlers to send 404 status.
Clear error messages improve user experience and debugging.
Practice
Solution
Step 1: Understand the role of not found exceptions
Not found exceptions indicate that a requested resource does not exist on the server.Step 2: Identify the correct response behavior
Returning a 404 HTTP status code clearly informs the client that the resource is missing.Final Answer:
To return a clear 404 status when a requested resource is missing -> Option DQuick Check:
Not found exceptions = 404 status [OK]
- Confusing not found with server errors
- Thinking it improves database speed
- Assuming it retries requests automatically
Solution
Step 1: Recall Spring Boot annotations for HTTP status
The @ResponseStatus annotation sets the HTTP status code for exceptions or controller methods.Step 2: Match the annotation to 404 status
Using @ResponseStatus(HttpStatus.NOT_FOUND) on a custom exception class sends 404 automatically.Final Answer:
@ResponseStatus(HttpStatus.NOT_FOUND) -> Option AQuick Check:
@ResponseStatus + NOT_FOUND = 404 [OK]
- Using @ExceptionHandler instead of @ResponseStatus
- Assuming @NotFoundException is a valid annotation
- Using incorrect annotation names
@GetMapping("/items/{id}")
public Item getItem(@PathVariable Long id) {
return itemRepository.findById(id)
.orElseThrow(() -> new ItemNotFoundException(id));
}What happens if the item with the given id does not exist?
Solution
Step 1: Analyze the use of orElseThrow
If the item is not found, orElseThrow triggers the custom ItemNotFoundException.Step 2: Understand exception handling with @ResponseStatus
If ItemNotFoundException is annotated with @ResponseStatus(HttpStatus.NOT_FOUND), Spring returns 404 status.Final Answer:
An ItemNotFoundException is thrown and HTTP 404 status is returned -> Option BQuick Check:
orElseThrow + @ResponseStatus = 404 error [OK]
- Assuming null is returned instead of exception
- Confusing 404 with 500 server error
- Thinking empty object is returned
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ProductNotFoundException extends RuntimeException {
public ProductNotFoundException(Long id) {
super("Product " + id + " not found");
}
}
@GetMapping("/products/{id}")
public Product getProduct(@PathVariable Long id) {
return productRepo.findById(id).orElseThrow(() -> new ProductNotFoundException(id));
}What is the likely problem if the client always receives HTTP 500 instead of 404 when a product is missing?
Solution
Step 1: Verify annotation presence
The exception class is correctly annotated with @ResponseStatus(HttpStatus.NOT_FOUND).Step 2: Understand Spring's exception mapping
If Spring returns 500, it means it does not recognize the exception mapping to 404, possibly due to package scanning or configuration issues.Final Answer:
The exception is thrown but Spring does not map it to 404 -> Option AQuick Check:
Annotated exception but 500 means mapping failed [OK]
- Assuming missing no-arg constructor causes 500
- Thinking @ResponseStatus is missing when it is present
- Believing explicit handler is always required
ResourceNotFoundException occurs. Which approach correctly achieves this?Solution
Step 1: Understand global exception handling
Using @ControllerAdvice with @ExceptionHandler allows centralized handling of exceptions across controllers.Step 2: Return ResponseEntity with 404 and JSON body
The handler method can build a ResponseEntity with HttpStatus.NOT_FOUND and a JSON error message for clients.Final Answer:
Create a class annotated with @ControllerAdvice and a method with @ExceptionHandler(ResourceNotFoundException.class) returning ResponseEntity with status 404 and error body -> Option CQuick Check:
Global handler + ResponseEntity = custom 404 JSON [OK]
- Relying only on @ResponseStatus without custom JSON body
- Annotating exception class as controller
- Manually throwing exceptions in every method
Ready to prove it?
Pass the test and this pattern moves unknown
