DEV Community

Cover image for ⚠️ Common Problems in Spring Boot Exception Handling (and How to Fix Them) πŸš€
Code Reacher
Code Reacher

Posted on

⚠️ Common Problems in Spring Boot Exception Handling (and How to Fix Them) πŸš€

Exception handling is an essential part of building robust applications in Spring Boot. However, developers often face issues like uncaught exceptions, improper error messages, and inconsistent responses. In this guide, I’ll walk you through the most common exception handling problems and how to solve them effectively.

πŸ”Ή Problem 1: Returning Generic Error Messages
By default, Spring Boot throws generic error messages, which don’t provide meaningful information to the client.

❌ Bad Practice:
If an exception occurs, the response might look like this:
{
"timestamp": "2025-04-06T14:22:00.123+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "No message available"
}

This is not helpful for debugging.

βœ… Solution: Use @ControllerAdvice for Global Exception Handling
Instead of returning generic errors, create a custom global exception handler:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleGlobalException(Exception ex) {
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("timestamp", LocalDateTime.now());
errorDetails.put("message", ex.getMessage());
errorDetails.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
}

Now, the error response is more meaningful and structured.

πŸ”Ή Problem 2: Handling Specific Exceptions Like EntityNotFoundException
Sometimes, fetching a resource that doesn’t exist causes 500 Internal Server Error instead of a 404 Not Found.

❌ Bad Practice:
If an entity is not found, it throws:
javax.persistence.EntityNotFoundException: No entity found for query

βœ… Solution: Handle Specific Exceptions
Modify the global exception handler to return 404 Not Found when an entity is missing:
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<Object> handleEntityNotFoundException(EntityNotFoundException ex) {
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("timestamp", LocalDateTime.now());
errorDetails.put("message", ex.getMessage());
errorDetails.put("status", HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}

Now, the API will return:
{
"timestamp": "2025-04-06T14:30:00.123+00:00",
"message": "User not found",
"status": 404
}

πŸ”Ή Problem 3: Handling Validation Errors in @RequestBody
If the user submits invalid data in a POST request, Spring Boot might throw MethodArgumentNotValidException with an unclear error message.

βœ… Solution: Customize Validation Error Handling
Modify your GlobalExceptionHandler to catch validation errors:
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Object> handleValidationException(MethodArgumentNotValidException ex) {
Map<String, Object> errors = new HashMap<>();
for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
errors.put(fieldError.getField(), fieldError.getDefaultMessage());
}
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}

Now, if a user submits invalid data, the response will be more readable:
{
"name": "Name is required",
"email": "Invalid email format"
}

πŸ”Ή Problem 4: Handling Custom Business Logic Exceptions
Let’s say we have a banking application, and a user tries to withdraw more money than available. Instead of throwing a generic RuntimeException, we can create a custom exception.

βœ… Solution: Create a Custom Exception Class
public class InsufficientBalanceException extends RuntimeException {
public InsufficientBalanceException(String message) {
super(message);
}
}

Now, handle it in GlobalExceptionHandler:
@ExceptionHandler(InsufficientBalanceException.class)
public ResponseEntity<Object> handleInsufficientBalance(InsufficientBalanceException ex) {
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("timestamp", LocalDateTime.now());
errorDetails.put("message", ex.getMessage());
errorDetails.put("status", HttpStatus.BAD_REQUEST.value());
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}

If a user tries to withdraw more than their balance, they will see this error:
{
"timestamp": "2025-04-06T14:45:00.123+00:00",
"message": "Insufficient balance for withdrawal",
"status": 400
}

🎯 Conclusion
πŸ”Ή Key Takeaways:
βœ… Use @ControllerAdvice for centralized exception handling.
βœ… Handle specific exceptions like EntityNotFoundException properly.
βœ… Improve validation error messages for better user experience.
βœ… Create custom exceptions for business logic errors.

By implementing these best practices, you’ll ensure your Spring Boot application is robust, user-friendly, and easy to debug. πŸš€

πŸ’¬ What’s Next?
What are some common Spring Boot exception handling issues you've faced? Drop a comment below!

πŸ”— If you found this guide helpful, check out my previous article: Getting Started with Spring Boot and PostgreSQL

πŸš€ Follow me for more backend development tips!

SpringBoot #Java #ExceptionHandling #BackendDevelopment #APIs #TechWriting

Top comments (0)