Search code examples
javajsonspringspring-mvcspring-annotations

How to get error text in controller from BindingResult?


I have an controller that returns JSON. It takes a form, which validates itself via spring annotations. I can get FieldError list from BindingResult, but they don't contain the text that a JSP would display in the <form:errors> tag. How can I get the error text to send back in JSON?

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody JSONResponse submit(@Valid AnswerForm answerForm, BindingResult result, Model model, HttpServletRequest request, HttpServletResponse response) {
    if (result.hasErrors()) {
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        JSONResponse r = new JSONResponse();
        r.setStatus(JSONResponseStatus.ERROR);
        //HOW DO I GET ERROR MESSAGES OUT OF BindingResult??? 
    } else {
        JSONResponse r = new JSONResponse();
        r.setStatus(JSONResponseStatus.OK);
        return r;
    }
}

JSONREsponse class is just a POJO

public class JSONResponse implements Serializable {
    private JSONResponseStatus status;
    private String error;
    private Map<String,String> errors;
    private Map<String,Object> data;
    
    // ...getters and setters...
}

Calling BindingResult.getAllErrors() returns an array of FieldError objects, but it does not have the actual errors.


Solution

  • Disclaimer: I still do not use Spring-MVC 3.0

    But i think the same approach used by Spring 2.5 can fullfil your needs

    for (Object object : bindingResult.getAllErrors()) {
        if(object instanceof FieldError) {
            FieldError fieldError = (FieldError) object;
    
            System.out.println(fieldError.getCode());
        }
    
        if(object instanceof ObjectError) {
            ObjectError objectError = (ObjectError) object;
    
            System.out.println(objectError.getCode());
        }
    }
    

    I hope it can be useful to you

    UPDATE

    If you want to get the message provided by your resource bundle, you need a registered messageSource instance (It must be called messageSource)

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames" value="ValidationMessages"/>
    </bean>
    

    Inject your MessageSource instance inside your View

    @Autowired
    private MessageSource messageSource;
    

    And to get your message, do as follows

    for (Object object : bindingResult.getAllErrors()) {
        if(object instanceof FieldError) {
            FieldError fieldError = (FieldError) object;
    
            /**
              * Use null as second parameter if you do not use i18n (internationalization)
              */
    
            String message = messageSource.getMessage(fieldError, null);
        }
    }
    

    Your Validator should looks like

    /**
      * Use null as fourth parameter if you do not want a default message
      */
    errors.rejectValue("<FIELD_NAME_GOES_HERE>", "answerform.questionId.invalid", new Object [] {"123"}, null);