Spring Boot Exception Handling for RESTful Services Errors


350,000 Learners are learning everyday with our Best Selling Courses : Microservices, Spring, Spring Boot, Web Services, Hibernate, Full Stack React, Full Stack Angular, Python, Spring Interview Guide, Java Interview, Java Functional Programming, AWS, Docker, Kubernetes, PCF, AWS Fargate and Azure

This guide will help you implement effective exception/error handling for a REST API/Service with Spring Boot.

You will learn

  • What is exception handling?
  • Why do you need exception handling?
  • What are the default exception handling capabilities provided by Spring Boot?
  • How to implement exception handling with Spring Boot for RESTful Services?
  • What are different return statuses you can use based on the API?
  • How/What to think when you design error handling for REST API?

Free Courses - Learn in 10 Steps

Project Code Structure

Following screenshot shows the structure of the project we will create. Image

A few details:

  • SpringBoot2RestServiceApplication.java - The Spring Boot Application class generated with Spring Initializer. This class acts as the launching point for application.
  • pom.xml - Contains all the dependencies needed to build this project. We will use Spring Boot Starter AOP.
  • Student.java - Student JPA Entity
  • StudentRepository.java - Student JPA Repository. This is created using Spring Data JpaRepository.
  • StudentResource.java - Spring Rest Controller exposing all services on the student resource.
  • CustomizedResponseEntityExceptionHandler.java - Component to implement global exception handling and customize the response based on the exception type.
  • ErrorDetails.java - Response Bean to use when exceptions are thrown from API.
  • StudentNotFoundException.java - Exception thrown from resources when student is not found.
  • data.sql - Initial data for the student table. Spring Boot would execute this script after the tables are created from the entities.

Tools you will need

  • Maven 3.0+ is your build tool
  • Your favorite IDE. We use Eclipse.
  • JDK 1.8+

Complete Maven Project With Code Examples

Our Github repository has all the code examples - https://github.com/in28minutes/spring-boot-examples/tree/master/spring-boot-2-rest-service-exception-handling

What is Exception Handling?

Consider these

  • What do you do when something goes wrong in your RESTful API?
  • What do you do when you get an invalid request?
  • What do you do when you something unexpected happens?

Think. What should you do?

Can I just return a Page Not Found - 404? Can I return a generic message Something went wrong.. Is that good enough?

One of the core design principles for RESTful services is

Think about the consumer

So, what should you when an error or exception happens in a RESTful service?

You should return a proper error response

  • Clear message indicating what went wrong and what the consumer can do to fix the error.
  • Include information necessary to solve the error.
  • Proper Response Status based on the context.
  • Do not include sensitive information in the response.

Response Statuses for Errors

Use appropriate status code based on the error.

  • 404 - RESOURCE NOT FOUND
  • 400 - BAD REQUEST
  • 401 - UNAUTHORIZED
  • 415 - UNSUPPORTED TYPE - Representation not supported for the resource
  • 500 - SERVER ERROR

Let’s consider a few HTTP Methods:

  • GET : Should not update anything. Should be idempotent (same result in multiple calls). Possible Return Codes 200 (OK) + 404 (NOT FOUND) +400 (BAD REQUEST)
  • POST : Should create new resource. Ideally return JSON with link to newly created resource. Same return codes as get possible. In addition - Return code 201 (CREATED) can be used.
  • PUT : Update a known resource. ex: update client details. Possible Return Codes : 200(OK) + 404 (NOT FOUND) +400 (BAD REQUEST)
  • DELETE : Used to delete a resource. Possible Return Codes : 200(OK).

500 - SERVER ERROR is possible with all the above HTTP methods. In the case of a 500, include the contact details of the help desk in the response.

Free Courses - Learn in 10 Steps

Bootstrapping a Project with REST Resouce

In the previous article in the series - http://www.springboottutorial.com/spring-boot-crud-rest-service-with-jpa-hibernate, we set up a simple restful service with a resource exposing CRUD methods.

We will use the same example to discuss about Exception Handling.

Default Exception Handling with Spring Boot

Spring Boot provides good default implementation for exception handling for RESTful Services. Let’s quickly look at the default Exception Handling features provided by Spring Boot.

Resource Not Present

Heres what happens when you fire a request to a non existent resource http://localhost:8080/some-dummy-url

{
  "timestamp": 1512713804164,
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/some-dummy-url"
}

Thats a cool error response. It contains all the details that are typically needed.


85,000 subscribers are learning AWS, Docker, Kubernetes, Spring Boot and Microservices on our Youtube Channel.

  SUBSCRIBE and Start Learning Now!


What happens when you throw an Exception?

Let’s see what Spring Boot does when an exception is thrown from a Resource.

Lets create a StudentNotFoundException.

/src/main/java/com/in28minutes/springboot/rest/example/student/StudentNotFoundException.java

public class StudentNotFoundException extends RuntimeException {

  public StudentNotFoundException(String exception) {
    super(exception);
  }

}

Let’s enhance the GET method to throw this exception when a student is not found.

  @GetMapping("/students/{id}")
  public Resource<Student> retrieveStudent(@PathVariable long id) {
    Optional<Student> student = studentRepository.findById(id);

    if (!student.isPresent())
      throw new StudentNotFoundException("id-" + id);

    Resource<Student> resource = new Resource<Student>(student.get());

    ControllerLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retrieveAllStudents());

    resource.add(linkTo.withRel("all-students"));

    return resource;
  }

This is the response when you try getting details of a non existing student http://localhost:8080/students/9.

{
  "timestamp": 1512714275589,
  "status": 500,
  "error": "Internal Server Error",
  "message": "id-9",
  "path": "/students/9"
}

One thing I do not like is the status code of the response. It is 500 - Server Error. Actually, the error is with the request. So, I would rather return a 404 - Resource not found.

Let’s see how to customize this and more in the next section.

Customizing Exception Handling with Spring Boot

A combination of Spring and Spring Boot provide multiple options to customize responses for errors.

Customizing Return Status for a Specific Exception

You can specify the Response Status for a specific exception along with the definition of the Exception with ‘@ResponseStatus’ annotation.

@ResponseStatus(HttpStatus.NOT_FOUND)
public class StudentNotFoundException extends RuntimeException {

This is the response when you try getting details of a non existing student http://localhost:8080/students/9.

{
  "timestamp": 1512714594153,
  "status": 404,
  "error": "Not Found",
  "message": "id-9",
  "path": "/students/9"
}

Customizing Error Response Structure

Default error response provided by Spring Boot contains all the details that are typically needed.

However, you might want to create a framework independent response structure for your organization. In that case, you can define a specific error response structure.

Let’s define a simple error response bean.

public class ErrorDetails {
  private Date timestamp;
  private String message;
  private String details;

  public ErrorDetails(Date timestamp, String message, String details) {
    super();
    this.timestamp = timestamp;
    this.message = message;
    this.details = details;
  }

To use ErrorDetails to return the error response, let’s define a ControllerAdvice as shown below.

@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler(StudentNotFoundException.class)
  public final ResponseEntity<ErrorDetails> handleUserNotFoundException(StudentNotFoundException ex, WebRequest request) {
    ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(),
        request.getDescription(false));
    return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
  }

Notes

  • @ExceptionHandler(StudentNotFoundException.class) indicates that this method would handle exceptions of the specific type.
  • new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND) - Create an error response object and return it with a specific Http Status.

This is the response when you try getting details of a non existing student http://localhost:8080/students/9.

{
  "timestamp": 1512714887537,
  "message": "id-9",
  "details": "uri=/students/9"
}

Response uses the custom error structure that we had defined earlier.

Using Error Response Structure for all Exceptions

You can further enhance CustomizedResponseEntityExceptionHandler to handle all other exceptions.

@ExceptionHandler(Exception.class)
public final ResponseEntity<ErrorDetails> handleAllExceptions(Exception ex, WebRequest request) {
  ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(),
      request.getDescription(false));
  return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}

Complete Code Example

Our Github repository has all the code examples - https://github.com/in28minutes/spring-boot-examples/tree/master/spring-boot-2-rest-service-exception-handling

What to Learn Next?

350,000 Learners are learning everyday with our Best Selling Courses : Microservices, Spring, Spring Boot, Web Services, Hibernate, Full Stack React, Full Stack Angular, Python, Spring Interview Guide, Java Interview, Java Functional Programming, AWS, Docker, Kubernetes, PCF, AWS Fargate and Azure


85,000 Subscribers are learning from our Free Videos on YouTube : JSP Servlets, Spring, Spring Boot, Spring MVC, Hibernate, Eclipse, Maven, JUnit, Mockito, Full Stack - React, Full Stack - Angular, Docker, Kubernetes, AWS, AWS Fargate, PCF and Azure


Here are the recommend articles to read next : Spring Interview Questions, Spring Boot Interview Questions, Microservices, Hibernate, Spring Security, REST API with Spring Boot, Full Stack with React, SOAP Web Services, Exception Handling, Embedded Servers, Spring Data Rest, Spring vs Spring MVC vs Spring Boot, Building Web Application and Spring Data JPA. You can checkout all our 100+ articles here - All Articles.


Do not know where to start your learning journey? Check out our amazing learning paths: Learning Path 01 - Spring and Spring Boot Web Applications and API Developer, Learning Path 02 - Full Stack Developer with Spring Boot, React & Angular, Learning Path 03 - Cloud Microservices Developer with Docker and Kubernetes, Learning Path 04 - Learn Cloud with Spring Boot, AWS, Azure and PCF and Learning Path 05 - Learn AWS with Microservices, Docker and Kubernetes


Related Posts

Deploy Java Spring Boot Applications to AWS, Azure, GCP with Docker and Kubernetes

In this article, we focus our attention on the cloud. How to learn the cloud and deploy Java Spring Boot Applications to AWS, Azure, GCP with Docker and Kubernetes?

Software Design - Single Responsibility Principle - with examples

For me, Single Responsibility Principle is the most important design principle. What is Single Responsibility Principle? How do you use it? How does it help with making your software better? Let's get started.

Spring Boot Tutorials for Beginners

At in28Minutes, we are creating a number of tutorials with videos, articles & courses on Spring Boot for Beginners and Experienced Developers. This resources will help you learn and gain expertise at Spring Boot.

Microservices with Spring Boot and Java - Part 1 - Getting Started

Let's learn the basics of microservices and microservices architectures. We will also start looking at a basic implementation of a microservice with Spring Boot. We will create a couple of microservices and get them to talk to each other using Eureka Naming Server and Ribbon for Client Side Load Balancing. In part 1 of this series, lets get introduced to the concept of microservices and understand how to create great microservices with Spring Boot and Spring Cloud.

20+ Spring Boot Projects with Code Examples

At in28Minutes, we have created more than 20 projects with code examples on Github. We have 50+ articles explaining these projects. These code examples will you learn and gain expertise at Spring Boot.

REST API Best Practices - With Design Examples from Java and Spring Web Services

Designing Great REST API is important to have great microservices. How do you design your REST API? What are the best practices?

Index - 500+ Videos

At in28Minutes, we are creating a number of tutorials with videos, articles & courses on Spring Boot for Beginners and Experienced Developers. Here's a list of video tutorials and courses for you

Creating Spring Boot and React Java Full Stack Application with Maven

This guide helps you create a Java full stack application with all the CRUD (Create, Read, Update and Delete) features using React as Frontend framework and Spring Boot as the backend REST API. We use Maven as the build tool.

Creating a SOAP Web Service with Spring Boot Starter Web Services

Let's learn how to create a SOAP Web Service with Spring Boot Starter Web Services. We will take a Contract First approach by definining an XSD and exposing a WSDL from it.