How to Handle Exceptions in Java REST APIs

How to Handle Exceptions in Java REST APIs

When building REST APIs in Java (especially with Spring Boot), you need to handle errors gracefully.

Why?

  • To avoid exposing technical details to the user

  • To send clear and user-friendly error messages

  • To make your API more reliable and professional

Let’s learn how to handle exceptions step-by-step.


❌ What Is an Exception?

An exception is an unexpected event that occurs during the execution of your program.

Example:

  • Dividing by zero

  • Trying to access a file that doesn’t exist

  • Requesting a resource that isn’t found in the database

If not handled properly, these can crash your app or return ugly error messages to users.


✅ Goal: Return Clean Error Responses

Instead of this (default error):

json
{ "timestamp": "2025-06-26T12:00:00.000+00:00", "status": 500, "error": "Internal Server Error", "message": "NullPointerException", "path": "/api/user/5" }

You should return something like:

{ "status": 404, "message": "User not found", "timestamp": "2025-06-26T12:00:00Z" }

Let’s see how to do it.


🧱 Step 1: Create Custom Exception Classes

You can define your own exceptions to represent different error situations.

public class UserNotFoundException extends RuntimeException { public UserNotFoundException(String message) { super(message); } }

🧱 Step 2: Throw the Exception in Your Code

In your service or controller:

public User getUserById(Long id) { return userRepository.findById(id) .orElseThrow(() -> new UserNotFoundException("User with ID " + id + " not found")); }

🧱 Step 3: Create a Global Exception Handler

Use @ControllerAdvice and @ExceptionHandler to catch and return custom responses.

import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<Object> handleUserNotFound(UserNotFoundException ex) { Map<String, Object> errorBody = new HashMap<>(); errorBody.put("timestamp", LocalDateTime.now()); errorBody.put("status", HttpStatus.NOT_FOUND.value()); errorBody.put("message", ex.getMessage()); return new ResponseEntity<>(errorBody, HttpStatus.NOT_FOUND); } // handle generic errors @ExceptionHandler(Exception.class) public ResponseEntity<Object> handleOtherExceptions(Exception ex) { Map<String, Object> errorBody = new HashMap<>(); errorBody.put("timestamp", LocalDateTime.now()); errorBody.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value()); errorBody.put("message", "Something went wrong"); return new ResponseEntity<>(errorBody, HttpStatus.INTERNAL_SERVER_ERROR); } }

📌 Optional: Create an Error Response Model

You can also use a class for clean error structure:

public class ApiError { private int status; private String message; private LocalDateTime timestamp; // constructor, getters, setters }

Use this in your handler instead of a Map.


🔁 Summary of Steps

StepDescription
1Create custom exception classes
2Throw exceptions in your business logic
3Use @ControllerAdvice to catch exceptions globally
4Return clean, structured JSON responses

🌍 Why Global Exception Handling is Best

  • Keeps your controller code clean

  • Gives users consistent error messages

  • Helps log and debug problems more easily

  • Improves security by hiding technical details


✅ Best Practices

  • Always provide clear error messages

  • Don’t expose stack traces or internal logic

  • Use proper HTTP status codes (e.g., 404, 400, 500)

  • Group common exceptions (like validation errors)

  • Log errors for debugging and audits


🧾 Final Thoughts

Handling exceptions the right way makes your REST API:

  • Cleaner

  • More user-friendly

  • Easier to maintain

With Spring Boot, it’s easy to centralize your error handling using @ControllerAdvice.


Learn  Full Stack Java Course

Read More 


Comments

Popular posts from this blog

Why Choose Python for Full-Stack Web Development

How Generative AI Differs from Traditional AI

What is Tosca? An Introduction