How to get error text in controller from BindingResult
Solution 1
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);
Solution 2
I met this problem recently, and found an easier way (maybe it's the support of Spring 3)
List<FieldError> errors = bindingResult.getFieldErrors();
for (FieldError error : errors ) {
System.out.println (error.getObjectName() + " - " + error.getDefaultMessage());
}
There's no need to change/add the message source.
Solution 3
With Java 8 Streams
bindingResult
.getFieldErrors()
.stream()
.forEach(f -> System.out.println(f.getField() + ": " + f.getDefaultMessage()));
Solution 4
WebMvcConfigurerAdapter:
@Bean(name = "messageSourceAccessor")
public org.springframework.context.support.MessageSourceAccessor messageSourceAccessor() {
return new MessageSourceAccessor( messageSource());
}
Controller:
@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( "<br />");
}
Solution 5
BEAN XML:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>
<bean id="messageAccessor" class="org.springframework.context.support.MessageSourceAccessor">
<constructor-arg index="0" ref="messageSource"/>
</bean>
JAVA:
for (FieldError error : errors.getFieldErrors()) {
logger.debug(messageAccessor.getMessage(error));
}
NOTE: Calling Errors.getDefaultMessage() will not necessarily return the same message that is generated from the code + args. The defaultMessage is a separate value defined when calling the Errors.rejectValue() method. See Errors.rejectValue() API Here
Mike
Updated on February 09, 2021Comments
-
Mike over 3 years
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 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 doesn't have the actual errors.
-
Mike about 14 yearsLet's say I have following in ValidationMessages.properties: "answerform.questionId.invalid = Invalid question id: {0}." fieldError.getCode() will return "answerform.questionId.invalid", I am looking for the error itself, not the code, ex: "Invalid question id: 123"
-
armyofda12mnkeys almost 9 yearsThanks this helped me... if using internationalization then just pass the locale (and args if needed) to get the translated string to place in your JSON error object: messageSource.getMessage (fieldError.getCode(), fieldError.getArguments(), myQuestionnaire.getLocale ())
-
Hoàng Long over 6 years@J.Wincewicz: sorry for not approving your edit suggestion. The above code I what I have tested (and running) in Spring 3. Your code suggests using a new method, which I'm not 100% sure that it will work with this old version of Spring. You may post it as a separate answer or comments on this post, though.
-
Nubok over 6 yearsPerhaps a somewhat more detailled explanation would be helpful.
-
Simon over 5 yearsThe 'stream().forEach()' chain can be replaced with 'forEach()' docs.oracle.com/javase/8/docs/api/java/lang/…