web-dev-qa-db-fra.com

Amorçage printanier, comment utiliser @Valid avec List <T>

J'essaie de valider un projet Spring Boot. J'ai donc mis l'annotation @NotNull dans les champs d'entité. Dans le contrôleur, je le vérifie comme ceci:

@RequestMapping(value="", method = RequestMethod.POST)
public DataResponse add(@RequestBody @Valid Status status, BindingResult bindingResult) {
    if(bindingResult.hasErrors()) {
        return new DataResponse(false, bindingResult.toString());
    }

    statusService.add(status);

    return  new DataResponse(true, "");
}

Cela marche. Mais quand je le crée avec l'entrée List<Status> statuses, cela ne fonctionne pas.

@RequestMapping(value="/bulk", method = RequestMethod.POST)
public List<DataResponse> bulkAdd(@RequestBody @Valid List<Status> statuses, BindingResult bindingResult) {
    // some code here
}

En gros, ce que je veux, c'est appliquer un contrôle de validation, comme dans la méthode add, à chaque objet Status de la liste requestbody. Ainsi, l'expéditeur déterminera quels objets sont en défaut et lesquels ne le sont pas.

Comment puis-je faire cela d'une manière simple et rapide?

8
kalahari

Ma suggestion immédiate est d’envelopper la liste dans un autre haricot POJO. Et utilisez-le comme paramètre de corps de requête.

Dans votre exemple.

@RequestMapping(value="/bulk", method = RequestMethod.POST)
public List<DataResponse> bulkAdd(@RequestBody @Valid StatusList statusList, BindingResult bindingResult) {
// some code here
}

et StatusList.Java seront

@Valid
private List<Status> statuses;
//Getter //Setter //Constructors

Je ne l'ai pas essayé cependant.

Update: La réponse acceptée dans ce SO link fournit une bonne explication du fait que la validation des beans n'est pas prise en charge sur les listes.

10
Ameen.M

Il suffit de marquer le contrôleur avec @Validated annotation.

Il lancera ConstraintViolationException, vous voudrez donc probablement le mapper sur 400: BAD_REQUEST:

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice(annotations = Validated.class)
public class ValidatedExceptionHandler {

    @ExceptionHandler
    public ResponseEntity<Object> handle(ConstraintViolationException exception) {

        List<String> errors = exception.getConstraintViolations()
                                       .stream()
                                       .map(this::toString)
                                       .collect(Collectors.toList());

        return new ResponseEntity<>(new ErrorResponseBody(exception.getLocalizedMessage(), errors),
                                    HttpStatus.BAD_REQUEST);
    }

    private String toString(ConstraintViolation<?> violation) {
        return Formatter.format("{} {}: {}",
                                violation.getRootBeanClass().getName(),
                                violation.getPropertyPath(),
                                violation.getMessage());
    }

    public static class ErrorResponseBody {
        private String message;
        private List<String> errors;
    }
}
0
Max Farsikov