eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this article, we’ll explore using ProblemDetail to return errors in Spring Boot applications. Whether we’re handling REST APIs or reactive streams, it offers a standardized way to communicate errors to clients.

Let’s dive into why we’d care about it. We’ll explore how error handling was done before its introduction, then, we’ll also discuss the specifications behind this powerful tool. Finally, we’ll learn how to prepare error responses using it.

2. Why Should We Care About ProblemDetail?

Using ProblemDetail to standardize error responses is crucial for any API.

It helps clients understand and handle errors, improving the API’s usability and debuggability. This leads to a better developer experience and more robust applications.

Adopting it can also help provide more informative error messages that are essential for maintaining and troubleshooting our services.

3. Traditional Error Handling Approaches

Before ProblemDetail, we often implemented custom exception handlers and response entities to handle errors in Spring Boot. We’d create custom error response structures. That resulted in inconsistencies across different APIs.

Also, this approach required a lot of boilerplate code. Moreover, it lacked a standardized way to represent errors, making it difficult for clients to parse and understand error messages uniformly.

4. ProblemDetail Specification

The ProblemDetail specification is part of the RFC 7807 standard.  It defines a consistent structure for error responses, including fields like type, title, status, detail, and instance. This standardization helps API developers and consumers by providing a common format for error information.

Implementing ProblemDetail ensures that our error responses are predictable and easy to understand. That in turn improves overall communication between our API and its clients.

Next, we’ll look at implementing it in our Spring Boot application, starting with basic setup and configuration.

5. Implementing ProblemDetail in Spring Boot

There are multiple ways to implement problem details in Spring Boot.

5.1. Enabling ProblemDetail Using Application Property

First, we can add a property to enable it. For RESTful service, we add the following property to application.properties:

spring.mvc.problemdetails.enabled=true

This property enables the automatic use of ProblemDetail for error handling in MVC (servlet stack) based applications.

For reactive applications, we’d add the following property:

spring.webflux.problemdetails.enabled=true

Once enabled, Spring reports errors using ProblemDetail:

{
    "type": "about:blank",
    "title": "Bad Request",
    "status": 400,
    "detail": "Invalid request content.",
    "instance": "/sales/calculate"
}

This property provides ProblemDetail automatically in error handling. Also, we can turn it off if it’s not needed.

5.2. Implementing ProblemDetail in Exception Handler

Global exception handlers implement centralized error handling in the Spring Boot REST applications.

Let’s consider a simple REST service to calculate discounted prices.

It takes an operation request and returns the result. Additionally, it also performs input validation and enforces business rules.

Let’s see the implementation of the request:

public record OperationRequest(
    @NotNull(message = "Base price should be greater than zero.")
    @Positive(message = "Base price should be greater than zero.")
        Double basePrice,
    @Nullable @Positive(message = "Discount should be greater than zero when provided.")
        Double discount) {}

Here is the implementation of the result:

public record OperationResult(
    @Positive(message = "Base price should be greater than zero.") Double basePrice,
    @Nullable @Positive(message = "Discount should be greater than zero when provided.")
        Double discount,
    @Nullable @Positive(message = "Selling price should be greater than zero.")
        Double sellingPrice) {}

And, here’s the implementation of the invalid operation exception:

public class InvalidInputException extends RuntimeException {

    public InvalidInputException(String s) {
        super(s);
    }
}

Now, let’s implement the REST controller to serve the endpoint:

@RestController
@RequestMapping("sales")
public class SalesController {

    @PostMapping("/calculate")
    public ResponseEntity<OperationResult> calculate(
        @Validated @RequestBody OperationRequest operationRequest) {
    
        OperationResult operationResult = null;
        Double discount = operationRequest.discount();
        if (discount == null) {
            operationResult =
                new OperationResult(operationRequest.basePrice(), null, operationRequest.basePrice());
        } else {
            if (discount.intValue() >= 100) {
                throw new InvalidInputException("Free sale is not allowed.");
            } else if (discount.intValue() > 30) {
                throw new IllegalArgumentException("Discount greater than 30% not allowed.");
            } else {
                operationResult = new OperationResult(operationRequest.basePrice(),
                    discount,
                    operationRequest.basePrice() * (100 - discount) / 100);
            }
        }
        return ResponseEntity.ok(operationResult);
    }
}

The SalesController class processes HTTP POST requests at the “/sales/calculate” endpoint.

It checks and validates an OperationRequest object. If the request is valid, it calculates the sale price, considering an optional discount. It throws exceptions if the discount is invalid (more than 100% or more than 30%). If the discount is valid, it calculates the final price by applying it and returns an OperationResult wrapped in a ResponseEntity.

Let’s now see how to implement ProblemDetail in the global exception handler:

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(InvalidInputException.class)
    public ProblemDetail handleInvalidInputException(InvalidInputException e, WebRequest request) {
        ProblemDetail problemDetail
            = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage());
        problemDetail.setInstance(URI.create("discount"));
        return problemDetail;
    }
}

The GlobalExceptionHandler class, annotated with @RestControllerAdvice, extends ResponseEntityExceptionHandler to provide centralized exception handling in a Spring Boot application.

It defines a method to handle InvalidInputException exceptions. When this exception occurs, it creates a ProblemDetail object with a BAD_REQUEST status and the exception’s message. Also, it sets the instance to a URI (“discount”) to indicate the specific context of the error.

This standardized error response provides clear and detailed information to the client about what went wrong.

The ResponseEntityExceptionHandler is a class that is convenient for handling exceptions in a standardized way across applications. Thus, the process of converting exceptions into meaningful HTTP responses is simplified. Moreover, it provides methods to handle common Spring MVC exceptions like MissingServletRequestParameterException, MethodArgumentNotValidException, etc out of the box using ProblemDetail.

5.3. Testing ProblemDetail Implementation

Let’s now test our functionality:

@Test
void givenFreeSale_whenSellingPriceIsCalculated_thenReturnError() throws Exception {

    OperationRequest operationRequest = new OperationRequest(100.0, 140.0);
    mockMvc
      .perform(MockMvcRequestBuilders.post("/sales/calculate")
      .content(toJson(operationRequest))
      .contentType(MediaType.APPLICATION_JSON))
      .andDo(print())
      .andExpectAll(status().isBadRequest(),
        jsonPath("$.title").value(HttpStatus.BAD_REQUEST.getReasonPhrase()),
        jsonPath("$.status").value(HttpStatus.BAD_REQUEST.value()),
        jsonPath("$.detail").value("Free sale is not allowed."),
        jsonPath("$.instance").value("discount"))
      .andReturn();
}

In this SalesControllerUnitTest, we’ve autowired the MockMvc and ObjectMapper for testing the SalesController.

The test method givenFreeSale_whenSellingPriceIsCalculated_thenReturnError() simulates a POST request to the “/sales/calculate” endpoint with an OperationRequest containing a base price of 100.0 and a discount of 140.0. So, this should trigger the InvalidOperandException in the controller.

Finally, we verify the response of type BadRequest with a ProblemDetail indicating that “Free sale is not allowed.”

6. Conclusion

In this tutorial, we explored ProblemDetails, its specification, and its implementation in a Spring Boot REST application. Then, we discussed the advantages over traditional error handling, and how to use it in servlet and reactive stacks.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)
1 Comment
Oldest
Newest
Inline Feedbacks
View all comments