Cómo obtener el texto de error en el controlador desde BindingResult

Tengo un controlador que devuelve JSON. Toma una forma, que se valida a sí misma a través de anotaciones de spring. Puedo obtener la lista FieldError de BindingResult, pero no contienen el texto que un JSP mostraría en la etiqueta. ¿Cómo puedo obtener el texto de error para enviar de vuelta en 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; } } 

La clase JSONREsponse es solo un POJO

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

Llamar a BindingResult.getAllErrors () devuelve una matriz de objetos FieldError, pero no tiene los errores reales.

Descargo de responsabilidad: todavía no uso Spring-MVC 3.0

Pero creo que el mismo enfoque utilizado por Spring 2.5 puede satisfacer sus necesidades

 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()); } } 

Espero que te pueda ser útil

ACTUALIZAR

Si desea obtener el mensaje proporcionado por su paquete de recursos, necesita una instancia de messageSource registrada ( debe llamarse messageSource)

    

Inyecte su instancia de MessageSource dentro de su vista

 @Autowired private MessageSource messageSource; 

Y para recibir su mensaje, haga lo siguiente

 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); } } 

Su Validator debería verse como

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

Conocí este problema recientemente, y encontré una manera más fácil (tal vez sea el soporte de Spring 3)

  List errors = bindingResult.getFieldErrors(); for (FieldError error : errors ) { System.out.println (error.getObjectName() + " - " + error.getDefaultMessage()); } 

No es necesario cambiar / agregar el origen del mensaje.

Con Java 8 Streams

 bindingResult .getFieldErrors() .stream() .forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage())); 

BEAN XML:

    messages       

JAVA:

 for (FieldError error : errors.getFieldErrors()) { logger.debug(messageAccessor.getMessage(error)); } 

NOTA: Llamar a Errors.getDefaultMessage () no devolverá necesariamente el mismo mensaje que se genera desde el código + args. El defaultMessage es un valor separado definido al llamar al método Errors.rejectValue (). Ver la API Errors.rejectValue () aquí

WebMvcConfigurerAdapter:

 @Bean(name = "messageSourceAccessor") public org.springframework.context.support.MessageSourceAccessor messageSourceAccessor() { return new MessageSourceAccessor( messageSource()); } 

Controlador:

 @Autowired @Qualifier("messageSourceAccessor") private MessageSourceAccessor messageSourceAccessor; ... StringBuilder sb = new StringBuilder(); for (ObjectError error : result.getAllErrors()) { if ( error instanceof FieldError) { FieldError fe = (FieldError) error; sb.append( fe.getField()); sb.append( ": "); } sb.append( messageSourceAccessor.getMessage( error)); sb.append( "
"); }