The controller:
@RestController
@RequestMapping(value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
@Validated
public class ApiController {
@PostMapping(value = "/in",
consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<InitResponse> inPost(
@ApiParam(required = true) @Valid @RequestBody InRequest inRequest) {
LOG.info("inPost request was received = {}", inRequest);
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
The exception handler:
@ControllerAdvice(assignableTypes = ApiController .class, annotations = RestController.class)
public class InExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<INErrors> handleConstraintViolation(ConstraintViolationException ex) {
LOG.info("handleConstraintViolation was trigerred");
INError INError = new INError(HttpStatus.BAD_REQUEST.toString(), ex.getLocalizedMessage());
return new ResponseEntity<>(new INErrors(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<INErrors> handleMethodArgumentConstraintViolation(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
List<FieldError> fieldErrors = result.getFieldErrors();
return new ResponseEntity<>(processFieldErrors(fieldErrors), HttpStatus.BAD_REQUEST);
}
}
If the InRequest has all fields within the javax validation constraint then I get the right code, but when a field doesn't match validation I just get 400 response code. There are other exception handlers defined but I've put breakpoints everywhere and nothing is triggered.
I also added the log4j property:
log4j.logger.org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod=DEBUG,stdout
but this didn't produce any additional output when debugging. I'm expecting to also to have the INErrors object sent back, but it doesn't even enter either one of the 2 handling methods.
This is happening because Spring's default exception handler handles all WebMvc's standard exceptions by itself and then delegates unhandled exceptions to user-defined
@ExceptionHandler
methods.In your case
@Valid
constraint violation throws Spring'sMethodArgumentNotValidException
which is handled byResponseEntityExceptionHandler#handleMethodArgumentNotValid
. So, to change the default behaviour for this exception, you need to override this method in your@ControllerAdivce
.EDIT: I saw that you're using both
assignableTypes
andannotations
for@ControllerAdvice
exception handler. This makes Spring register one exception handler for all@RestController
s. Try using eitherassignableTypes
orannotations
.As an option, you can create your custom annotation for different exception handlers.
Following code prints "one" when invalid data supplied to
/one
and "two" when data was sent to "/two".