Paul McKenzie
Paul McKenzie

Reputation: 20096

Capturing Hibernate Validator message text in Spring MVC

I am working on a REST api using Spring-MVC and json. I running my automatic tests using Jetty and an in-memory database. I want to test that posting an invalid domain object gives me the error message from the @NotEmpty annotation. But all I get is the default Jetty 400 Bad Request page.

I have a domain class with some validation:

@Entity
public class Company {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotEmpty(message = "Name is a required field")
    private String name;

    /* getters, setters */
}

Here's the controller

@Controller
public class CompanyController {
    @RequestMapping(value = "/company", 
        method = RequestMethod.POST, 
        consumes = "application/json")
    public void createCompany(
        @Valid @RequestBody final Company company,
        final HttpServletResponse response) {

        //persist company
        response.setStatus(HttpServletResponse.SC_CREATED);
        response.setHeader("location", "/company/" + company.getId());
    }
}

How can I get the value "Name is a required field" returned as part of the response?

Upvotes: 1

Views: 1702

Answers (3)

beerbajay
beerbajay

Reputation: 20270

Spring 3.2 variant using ControllerAdvice and ResponseEntityExceptionHandler:

@ControllerAdvice
public class ErrorHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> 
    handleMethodArgumentNotValid(MethodArgumentNotValidException e,
                                 HttpHeaders headers, HttpStatus status,
                                 WebRequest request) {
        BindingResult bindingResult = e.getBindingResult();
        ArrayList<String> errors = new ArrayList<String>();
        for (ObjectError error : bindingResult.getGlobalErrors()) {
            errors.add(error.getDefaultMessage());
        }
        for (FieldError error : bindingResult.getFieldErrors()) {
            errors.add(
              String.format("%s %s", error.getField(), error.getDefaultMessage())
            );
        }
        return handleExceptionInternal(e, StringUtils.join(errors, ", "),
                headers, HttpStatus.UNPROCESSABLE_ENTITY, request);
}

Upvotes: 1

Paul McKenzie
Paul McKenzie

Reputation: 20096

This does it:

@ExceptionHandler(value = MethodArgumentNotValidException.class)
public void exceptionHandler(final MethodArgumentNotValidException ex, 
                     final HttpServletResponse response) throws IOException {

    for (final ObjectError objectError : ex.getBindingResult().getAllErrors()) {
        response.getWriter().append(objectError.getDefaultMessage()).append(".");
    }
    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}

Upvotes: 2

atrain
atrain

Reputation: 9255

You need to add a BindingResult to your handler method. That object will automatically add the results to the Model, which can then be easily accessed from the Spring Forms taglib.

Upvotes: 0

Related Questions