I have a simple Spring Rest Controller with some validation. My understanding is that validation failures would throw a MethodArgumentNotValidException. However, my code throws a BindException instead. In debug messages, I also see the app returning a null ModelAndView.
Why would a Rest Controller throw BindException or return a null ModelAndView?
Note: I am testing my web application using curl and making an HTTP POST
curl -X POST http://localhost:8080/tasks
I am intentionally omitting the "name" parameter which is a required field marked with @NotNull and @NotBlank annotations.
My Controller:
@RestController
public class TasksController {
private static Logger logger = Logger.getLogger(TasksController.class);
@Autowired
private MessageSource messageSource;
@Autowired
private Validator validator;
@InitBinder
protected void initBinder(WebDataBinder binder){
binder.setValidator(this.validator);
}
@RequestMapping(value = "/tasks", method = RequestMethod.POST)
public Task createTask(@Valid TasksCommand tasksCommand){
Task task = new Task();
task.setName(tasksCommand.getName());
task.setDue(tasksCommand.getDue());
task.setCategory(tasksCommand.getCategory());
return task;
}
}
My "command" class (that contains validation annotations)
public class TasksCommand {
@NotBlank
@NotNull
private String name;
private Calendar due;
private String category;
... getters & setters ommitted ...
}
My RestErrorHandler class:
@ControllerAdvice
public class RestErrorHandler {
private static Logger logger = Logger.getLogger(RestErrorHandler.class);
@Autowired
private MessageSource messageSource;
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorsList processErrors(MethodArgumentNotValidException ex){
logger.info("error handler invoked ...");
BindingResult result = ex.getBindingResult();
List<FieldError> fieldErrorList = result.getFieldErrors();
ErrorsList errorsList = new ErrorsList();
for(FieldError fieldError: fieldErrorList){
Locale currentLocale = LocaleContextHolder.getLocale();
String errorMessage = messageSource.getMessage(fieldError, currentLocale);
logger.info("adding error message - " + errorMessage + " - to errorsList");
errorsList.addFieldError(fieldError.getField(), errorMessage);
}
return errorsList;
}
}
The processErrors method marked with @ExceptionHandler(...) annotation never gets called. If I try to catch a BindException using @ExceptionHandler(...) annotation, that handler method does get invoked.
I have couple of support classes - Task, TaskCommand, Error and ErrorsList - that I can post code for if needed.
@RestController
. It works when I use@Controller
combined with@RequestBody
and@ResponseBody
. Did you work this out by any chance? – Bereniceberenson