web-dev-qa-db-fra.com

Comment obtenir le texte d'erreur dans le contrôleur à partir de BindingResult

J'ai un contrôleur qui retourne JSON. Il prend une forme qui se valide via des annotations de printemps. Je peux obtenir la liste FieldError de BindingResult, mais ils ne contiennent pas le texte qu'un JSP afficherait dans la balise. Comment obtenir le texte d'erreur à renvoyer 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 classe JSONREsponse n'est qu'un 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...
}

L'appel de BindingResult.getAllErrors () renvoie un tableau d'objets FieldError, mais il n'a pas les erreurs réelles.

27
Mike

Avertissement: je n'utilise toujours pas Spring-MVC 3.0

Mais je pense que la même approche utilisée par Spring 2.5 peut répondre à vos besoins

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

J'espère que cela peut vous être utile

MISE À JOUR

Si vous souhaitez obtenir le message fourni par votre ensemble de ressources, vous avez besoin d'une instance de messageSource enregistrée (It must s'appelle messageSource)

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

Injectez votre instance MessageSource dans votre vue

@Autowired
private MessageSource messageSource;

Et pour faire passer votre message, procédez comme suit

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

Votre validateur devrait ressembler à

/**
  * 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);
33
Arthur Ronald

J'ai rencontré ce problème récemment et j'ai trouvé un moyen plus simple (c'est peut-être le support de Spring 3)

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

Il n'est pas nécessaire de modifier/ajouter la source du message.

24
Hoàng Long

Avec Java 8 flux

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

WebMvcConfigurerAdapter:

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

Contrôleur:

@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 />");
}
1

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

REMARQUE: L'appel à Errors.getDefaultMessage () ne renverra pas nécessairement le même message généré à partir du code + args. Le defaultMessage est une valeur distincte définie lors de l'appel de la méthode Errors.rejectValue (). Voir API Errors.rejectValue () ici

1
splashout