Mastering Error Handling in Spring Boot with ProblemDetails

Elevate your API’s error responses: Standardize, Inform, and Simplify with RFC 9457

Mastering Error Handling in Spring Boot with ProblemDetails
Image generated by Midjourney

Introduction

Hello everyone! In this article I will try to cover a game — changer for API error handling in Spring Boot — the ProblemDetails RFC. If you spent a long time wrestling with inconsistent error responses or scratching your head over how to structure your API’s error message, you’re in for a treat.

What is the deal with ProblemDetails?

Image by author

First of all the ProblemDetails is not just another Spring Boot feature — it is an IETF standard (RFC 9457) that defines a “problem detail” as a way to carry machine-readable details error in a HTTP response.

Since Spring Boot 3.0 the ProblemDetails are natively supported, making it easier than ever to implement this standard in your applications. Before diving into implementation details let’s answer the question “Why you should care?”

  1. Better client — side error handling
  2. Improved API documentation
  3. Consistency across your services

Implementation

In this article, I’m using Spring Boot 3.3.4 where ProblemDetails is enabled by default. If you are using an older version of Spring Boot you have to configure ProblemDetails manually.

package me.vrnsky.problemdetails.config; 
 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 
 
@Configuration 
public class ProblemDetailsConfig { 
 
    @Bean 
    public ResponseEntityExceptionHandler exceptionHandler() { 
      return new ResponseEntityExceptionHandler() { 
        @Override 
        protected ResponseEntity<Object> handleException(Exception exception,  
            @Nullable Object body, HttpHeaders headers, HttpStatusCode statusCode, 
            WebRequest request) { 
           ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(statusCode, ex.getMessage()); 
           problemDetail.setProperty("timestamp", Instant.now()); 
           problemDetail.setProperty("exception", ex.getClass().getName()); 
 
           return super.handleExceptionInternal(ex, problemDetail, headers, statusCode, request); 
    } 
}

Let’s now create a basic REST API Controller that will simulate fetching user data from storage.

@RestController 
@RequiredArgsConstructor 
public class UserController { 
 
  private final UserService userService; 
 
  @GetMapping("/user/{id}") 
  public User getUser(@PathVariable Long id) { 
    if (id <= 0) { 
      throw new IllegalArgumentException("User ID must be positive!"); 
    } 
 
    return userService.getUserById(id); 
  } 
 
   
  @Data 
  public static class User { 
     private Long id; 
     private String username; 
 } 
}

Let’s test our API with curl.

curl "http://localhost:8080/users/-1"

After hitting this URL we got following response.

{ 
  "type": "", 
  "title": "Bad Request", 
  "status": 400, 
  "detail": "User ID must be positive", 
  "instance": "/api/user/-1", 
  "timestamp": "2024-10-07T10:30:45.123Z", 
  "exception": "java.lang.IllegalArgumentException" 
}

We got a structured, consistent error response without having to manually construct it each time.

Improvements

The code above is agood fit for common and prototyping scenarios, you might want or have to customize it in real — world services. You can:

  1. Elevate custom exception types that map to specific HTTP status codes.
  2. Provide more context to your ProblemDetails, like error codes or links to documentation.

Conclusion

Applying ProblemDetails in your Spring Boot application is a small change that can lead to a big impact on the quality and consistency of your API. The traditional approach has served us well, meanwhile, ProblemDetails offers a more robust, standardized, and future — proof solution. You have to keep in mind that error handling it not only about reporting failures, it is also about providing actionable information that helps solve problems.

References

  1. Spring Documentation
  2. RFC 9457

Subscribe to Egor Voronianskii | Java Development and whatsoever

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe