0

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!

4
  • You don't show us enough code to be certain, but I suspect that you don't have @ControllerAdvice on the class that defines your error handling method. Commented Sep 11, 2014 at 18:29
  • Thanks for your comment. I've updated my post to include the majority of the classes. Originally the error handling was done in the main controller. I've extracted that out and put in an ExceptionHandlers class with the ControllerAdvice annotation, but I still get no json or xml response, just a 400. Commented Sep 11, 2014 at 18:38
  • What version of Spring are you using? Commented Sep 11, 2014 at 19:40
  • org.springframework:spring-webmvc:4.1.0.RELEASE Commented Sep 11, 2014 at 19:41

1 Answer 1

1

@ResponseStatus(HttpStatus.BAD_REQUEST) will set the status code to 400. However, the .andExpect(status().isOk()) snippet will compare the status code to 200, which will fail the test and line where you print the content will never be reached.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for pointing this out. This is true, and I've made a correction to the question. However, I need some kind of response, which should be json or xml, which I'm not getting. The response is simply empty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.