Closed as not planned
Closed as not planned
Description
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:
Placing the @ExceptionHandler
in the same class as the @Controller
works for both 3.1.6 and 3.2.0.