I have already gone through official Spring Boot tutorial, a couple of Stack Overflow posts including this, tried @Ordered(Order=HIGHEST_PRECEDENCE)
but any exception other than the ConstraintViolationException.class
is being handled by DefaultHandlerExceptionResolver
VERSIONS
- Spring Boot - 2.5.3
- Spring - 5.3.9
PROBLEM
I want any exception in MyRestController
be handled by handlers in ControllerAdvice
defined by me so that I can manipulate the response object before sending to the client.
@Validated
@RestController
@RequestMapping(value = "/myctx", produces = MediaType.APPLICATION_JSON_VALUE)
public class MyRestController {
private static final Logger logger = LoggerFactory.getLogger(MyRestController);
@RequestMapping(
path = "/{element}",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ApiResponse> findAndSave(
@Allowed(values = { "a1", "a2", "a3" }) @PathVariable String element,
@ValidateMetadata @RequestBody Metadata metadata) {
...
...
}
}
The annotations @Allowed
and @ValidateMetadata
defined by me are working as expected
@ControllerAdvice
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class ErrorControllerAdvice extends ResponseEntityExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(ErrorControllerAdvice.class);
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) {
ApiResponse apiResponse = ApiResponse.builder()
.timestamp(new Date())
.status(HttpStatus.BAD_REQUEST)
.message(ex.getLocalizedMessage())
.path(((ServletWebRequest) request).getRequest().getRequestURI())
//.metadata(metadata)
.build();
return handleExceptionInternal(ex, apiResponse, new HttpHeaders(), apiResponse.getStatus(), request);
}
@ExceptionHandler({ Exception.class })
public ResponseEntity<Object> handleAll(Exception ex, WebRequest request) throws Exception {
ResponseEntity<Object> tmpResponse = super.handleException(ex, request);
ResponseEntity<Object> response = new ResponseEntity<>("Response from catch-all exception handler", tmpResponse.getHeaders(), tmpResponse.getStatusCode());
return response;
}
}
At this point when I test my endpoint with a POST request and inject a ContraintViolation, my custom error response is sent to the client. However, for any other Exception, handleAll()
method in ErrorControllerAdvice
is not even invoked. For example, from the test code, I try to send a GET instead of a POST or change the URI to contain myct
instead of myctx
Why is it not working? Why do I get default error messages in case of the situations described above?
Update
I even tried throwing a NullPointerException from within the controller method but that also didn't invoke the handleAll()
method.