Exception Handling in REST API
Exception handling is a critical aspect of building robust and userfriendly REST APIs. When something goes wrong in your application — be it a validation error, a database issue, or an unexpected server error — it’s essential to handle these exceptions gracefully and provide meaningful feedback to the client. In this article, we’ll explore how to handle exceptions in REST APIs using Spring Boot, along with best practices and examples.
Why is Exception Handling Important?
1. Improved User Experience: Clients receive clear and meaningful error messages instead of cryptic stack traces.
2. Debugging and Maintenance: Proper exception handling makes it easier to identify and fix issues.
3. Consistency: Standardized error responses ensure consistency across your API.
Key Concepts in REST API Exception Handling
1. HTTP Status Codes
HTTP status codes are used to indicate the result of a client’s request. Some common status codes include:
2xx (Success): 200 OK, 201 Created
4xx (Client Errors): 400 Bad Request, 404 Not Found
5xx (Server Errors): 500 Internal Server Error
2. Error Response Structure
A well structured error response typically includes:
Status Code: The HTTP status code.
Message: A human readable error message.
Details: Additional information about the error (optional).
Timestamp: When the error occurred (optional).
Example:
{
"status": 404,
"message": "Resource not found",
"details": "The requested resource with ID 123 does not exist.",
"timestamp": "2023-10-25T12:34:56Z"
}Exception Handling in Spring Boot
Spring Boot provides several mechanisms to handle exceptions in REST APIs. Let’s explore them step by step.
1. Custom Exception Class
Create a custom exception class to represent specific errors in your application.
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}2. Global Exception Handler
Use the @ControllerAdvice and @ExceptionHandler annotations to create a global exception handler. This ensures that all exceptions are handled consistently across your application.
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse(
404,
ex.getMessage(),
"The requested resource was not found.",
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse(
500,
"An unexpected error occurred.",
ex.getMessage(),
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}3. Error Response Class
Get Pratik T’s stories in your inbox
Join Medium for free to get updates from this writer.
Create a class to represent the error response structure.
public class ErrorResponse {
private int status;
private String message;
private String details;
private LocalDateTime timestamp;
// Constructor, Getters, and Setters
}4. Throwing Exceptions in Service Layer
Throw custom exceptions in your service layer when specific conditions are met.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with ID: " + id));
}
}5. Example: REST Controller
Use the service layer in your controller and let the global exception handler manage exceptions.
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return new ResponseEntity<>(user, HttpStatus.OK);
}
}Best Practices for Exception Handling
1. Use Specific Exceptions: Create custom exceptions for specific error scenarios (e.g., ResourceNotFoundException, ValidationException).
2. Return Meaningful Error Messages: Provide clear and actionable error messages to the client.
3. Log Exceptions: Log exceptions for debugging and monitoring purposes.
4. Use HTTP Status Codes Correctly: Follow REST conventions for status codes (e.g., 404 for missing resources, 400 for bad requests).
5. Avoid Exposing Sensitive Information: Do not include stack traces or internal details in production error responses.
Example: Complete Workflow
Step 1: Client Sends a Request
GET /users/123Step 2: Service Layer Throws an Exception
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with ID: " + id));
}Step 3: Global Exception Handler Catches the Exception
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse(
404,
ex.getMessage(),
"The requested resource was not found.",
LocalDateTime.now()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}Step 4: Client Receives the Error Response
{
"status": 404,
"message": "User not found with ID: 123",
"details": "The requested resource was not found.",
"timestamp": "2023-10-25T12:34:56Z"
}Conclusion
Exception handling is a crucial part of building reliable and userfriendly REST APIs. By using custom exceptions, global exception handlers, and structured error responses, you can ensure that your API provides meaningful feedback to clients and simplifies debugging for developers.
In this article, we covered:
The importance of exception handling.
How to implement exception handling in Spring Boot.
Best practices for designing error responses.
With these techniques, you can build REST APIs that are robust, maintainable, and easy to use. Happy coding!
If you found this article helpful, feel free to share it with your network. Let me know your thoughts in the comments below!









