See UPDATE below.
I am trying to validate parameters passed in to the following RESTful endpoint.
@Controller
@RequestMapping(GlobalConstants.SERVICE_BASE_URL)
public class AuctionsController {
...
@ResponseBody
@RequestMapping( produces = {"application/json", "application/xml"},
method = RequestMethod.GET,
value = "v001/test")
public CommissionsResponse getAuctionCommission( @RequestParam(required = true) Integer someInteger,
@RequestParam(required = false) Integer otherInteger,
@RequestParam(required = true) BigDecimal price,
@RequestParam(required = true) String name) {
MyResponse response = new MyResponse();
response.setSomeInteger(someInteger);
response.setOtherInteger(otherInteger);
response.setPrice(price);
response.setName(name);
return response;
}
}
It's talked about here how to validate parameters using Spring's Web MVC. He creates a handler for this, which I've placed in an ExceptionHandlers class, and an error bean:
UPDATE-1::: The below method takes MethodArgumentNotValidException, which only works when a bean is not valid (that is, the bean would be an argument in the controller class that's marked with the annotation @Valid). So this will never work. I'd still like to be able to handle the 400 however, in the case where the end user enters a bad parameter. That is, for example, when the user enters a String for a parameter that should be a BigDecimal.
@ControllerAdvice
public class ExceptionHandlers {
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorMessage handleException(MethodArgumentNotValidException ex) {
List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
List<ObjectError> globalErrors = ex.getBindingResult().getGlobalErrors();
List<String> errors = new ArrayList<>(fieldErrors.size() + globalErrors.size());
String error;
for (FieldError fieldError : fieldErrors) {
error = fieldError.getField() + ", " + fieldError.getDefaultMessage();
errors.add(error);
}
for (ObjectError objectError : globalErrors) {
error = objectError.getObjectName() + ", " + objectError.getDefaultMessage();
errors.add(error);
}
return new ErrorMessage(errors);
}
}
..and the error bean
@XmlRootElement
public class ErrorMessage {
private List<String> errors;
public ErrorMessage() {
}
public ErrorMessage(List<String> errors) {
this.errors = errors;
}
public ErrorMessage(String error) {
this(Collections.singletonList(error));
}
public ErrorMessage(String ... errors) {
this(Arrays.asList(errors));
}
public List<String> getErrors() {
return errors;
}
public void setErrors(List<String> errors) {
this.errors = errors;
}
}
I've used the method below to try to catch the 400, which is being thrown with the following test. Here I'm trying to throw a 400 by using an incorrect value for the price parameter.
@Test
public void testTheEndpoint() throws Exception {
String url = "v001/test?someInteger=21&otherInteger=456&price=NOT_A_BIG_DECIMAL&name=test";
log.info("Testing Endpoint::: " + url);
MvcResult result = mockMvc.perform(get(url))
.andReturn();
log.info("RESPONSE::: " + result.getResponse().getContentAsString());
}
However, I get no error xml response using this. Instead my test just fails with a 400. Anyone mind telling me what I'm doing wrong here? Thanks!