Mastering Error Handling in Spring Boot with ProblemDetails
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?
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?”
- Better client — side error handling
- Improved API documentation
- 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);
}
}