Skip to content

@ExceptionHandler not called within @ControllerAdvice since Spring Framework 6.1 #31818

Closed as not planned
@agebhar1

Description

@agebhar1

After upgrade from Spring Boot 3.1.6 to 3.2.0 the @ExceptionHandler annotated method within a dedicated @ControllerAdvice (class) is not called anymore.

A minimal example is:

package com.example.demo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.UUID;

import static org.springframework.http.HttpStatus.BAD_REQUEST;

@SpringBootApplication
public class DemoApplication {

    record Content(String key, String value) {
    }

    @ControllerAdvice
    static class ItemControllerAdvice {

        private static final Logger logger = LoggerFactory.getLogger(ItemControllerAdvice.class);

        public ItemControllerAdvice() {
            logger.info("Create instance of {}.", getClass().getCanonicalName());
        }

        @ExceptionHandler(HttpMessageNotReadableException.class)
        public ProblemDetail handleHttpMessageNotReadable(HttpMessageNotReadableException exception) throws URISyntaxException {

            var instance = UUID.randomUUID();
            logger.error("Id: " + instance, exception);

            var problemDetail = ProblemDetail.forStatus(BAD_REQUEST);
            problemDetail.setTitle("Could not read provided data or did not validate.");
            problemDetail.setInstance(new URI("urn::uuid" + instance));

            return problemDetail;
        }

    }

    @Controller
    static class ItemController {

        private static final Logger logger = LoggerFactory.getLogger(ItemController.class);

        @PutMapping("/items/{item}")
        public ResponseEntity<Object> update(@PathVariable String item, @RequestBody List<Content> content) {
            logger.info("Update {} with {}.", item, content);
            return ResponseEntity.noContent().build();
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

application.yml:

spring:
  mvc:
    problemdetails:
      enabled: true

The expected return value for calling the endpoint with an invalid JSON is (Spring Boot 3.1.6):

$ curl -X PUT --location "http://localhost:8080/items/0" -H "Content-Type: application/json" -d '['
{"type":"about:blank","title":"Could not read provided data or did not validate.","status":400,"instance":"urn::uuid2ea314de-39bf-417e-9f52-796506111b41"}

With Spring Boot 3.2.0 the return value does not contain the custom error message:

curl -X PUT --location "http://localhost:8080/items/0" -H "Content-Type: application/json" -d '['
{"type":"about:blank","title":"Bad Request","status":400,"detail":"Failed to read request","instance":"/items/0"}

The difference in code execution start in org.springframework.web.method.support.InvocableHandlerMethod#doInvoke. The returned bridged method is different:

Spring Boot 3.1.6:
Bildschirmfoto vom 2023-12-12 08-07-16

Spring Boot 3.2.0:
Bildschirmfoto vom 2023-12-12 08-09-03

Placing the @ExceptionHandler in the same class as the @Controller works for both 3.1.6 and 3.2.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: webIssues in web modules (web, webmvc, webflux, websocket)status: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions