Validateurs manuels dans Spring

Implémentation de l'interface Validator du Spring

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Parfois les validations par annotations peuvent paraître compliquées à mettre en place. C'est pourquoi Spring a rendu possible la création des validateurs manuels.

Validateur manuel dans Spring

Dans le paragraphe précédent on a vu que pour valider les JavaBean dans Spring il suffisait d'utiliser les annotations adéquates. Cependant, ce n'est pas le seul moyen d'accomplir une validation. Dans certains cas on peut écrire le code d'un validateur. Il est important que celui-ci implémente l'interface org.springframework.validation.Validator.

Cette situation-là est un peu différente par rapport à deux précédentes. L'élément validé ne peut plus être accompagné de l'annotation @Valid ou @Validated. L'indication de l'élément à valider doit se faire explicitement dans le code, via DataBinder à qui on montrera quelle instance il faut valider avec quel validateur. Ensuite la récupération des erreurs se fait de la même manière que dans le cas d'une validation par annotations. Regardons cela dans le code d'un contrôleur :

@RequestMapping("/booking")
@Controller
public class BookingController {
    // only this method interests us
    @RequestMapping(value = "/do/{copy}", method = RequestMethod.POST)
    public String handleDoBooking(@ModelAttribute("booking") Booking booking, @PathVariable long copy, @LoggedUser AuthenticationFrontendUserDetails user, RedirectAttributes redAtt) {    
        // ..
        DataBinder binder = new DataBinder(booking);
        CustomDateEditor customDateEditor = new CustomDateEditor(new SimpleDateFormat("dd-MM-yyyy"), true);
        binder.registerCustomEditor(Date.class, customDateEditor);
        binder.setValidator(new BookingValidator(bookingService, request, csrfProtector));
        binder.validate();
        BindingResult results = binder.getBindingResult();
        if(results.hasErrors()) {
            // ...
        }
        // ...
    }
}

Le code se comporte comme indiqué précédemment. Passons maintenant à l'analyse du BookinValidator dont l'instance est créée dans la méthode setValidator() :

afficher le code

Regardons les méthodes une par une. Le constructeur d'abord, il prend en paramètre l'implémentation de l'interface BookingService. Comme on a expliqué dans l'article codage aux interfaces, ce service ne peut pas être injecté directement via @Autowired ou une propriété dans le fichier de configuration. C'est impossible car BookingValidator n'est pas un bean et BookingService doit être passé manuellement en paramètre.

Ensuite on a une méthode qui vérifie si l'objet à valider est supporté par la classe en question. Il s'agit d'une méthode dont le nom est bien explicite, supports().

La dernière méthode implémentée, la plus importante d'ailleurs, contient toute la logique de validation. On vérifie si les éléments passés ne sont pas null ou s'ils correspondent à des critères de validation (date d'emprunt après-demain ou si l'exemplaire n'est pas encore emprunté). On voit qu'à chaque fois où un attribut est invalide, on utilise l'instance de l'objet Errors en appelant la méthode rejectValue(). Cette fonction prend en paramètres (dans l'ordre spécifié dans l'exemple) :
- le nom du champ invalide
- le code du message d'erreur à afficher
- (concerne uniquement le champ bookingDate) une liste d'arguments récupérables par le message d'erreur
- le message par défaut qui sera affiché si le message n'est pas trouvé dans la liste des traductions

Bartosz KONIECZNY Validation

Une question ? Une remarque ?

*

*

Un conseil JavaScript

Un scroll avec dialog box de jQuery UI ?

Si vous voyez une barre horizontale qui apparaît après l'ouverture d'un dialog box sous IE8, il peut s'agit d'un problème de ce module pour le navigateur en question. Pour y remedier, on peut utiliser la méthode open() et forcer le navigateur à cacher cette bare. Prenons un exemple vivant :

var dialogBox = $(href).dialog({ autoOpen: false, closeOnEscape: true,
  open: function() {  
        $('body').css('overflow-x', 'hidden');
  },
  close: function() {
        $('body').css('overflow-x', 'auto');  
  }
});  
dialogBox.dialog("open");