Property editors

Changer un String en un Objet Java dans 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

Spring nous permet de travailler avec tous les types d'objets possibles et imaginables. Cependant, les servlets Java gèrent uniquement un seul type des paramètres : les String. Ces chaînes de caractères, comprises par exemples dans les formulaires, peuvent en fait représenter des objets plus complexes comme des collections ou des dates. Pour pouvoir opérer sur ces objets plus sophistiqués, on doit utiliser les property editors. Ils permettent de traduire un String en un objet souhaité.

Property editors dans Spring

Ces convertisseurs magiques s'appellent property editors et on pour but de transformer une chaîne de caractères en un objet souhaité. L'utilité de cette conversion peut être observée lors :
- de la définition des propriétés dans les beans
- du traitement de la requête HTTP quand il faut récupérer les types primitifs différents (chiffres, lettres) en fonction du type spécifié dans la méthode du contrôleur
- du traitement des formulaires où, par exemple, une chaîne de caractères nécessite d'être transformée en l'instance de la classe Date

Certains éditeurs sont pré-enregistrés dans Spring :
- ByteArrayPropertyEditor : à travers lui, String est transformé en une représentation bytes
- ClassEditor : traduit des String en Class;
- CustomBooleanEditor : adapté à la conversion vers les instances Boolean
- CustomCollectionEditor : permet de convertir les Collection
- CustomDateEditor : éditeur pour la classe java.util.Date
- CustomNumberEditor : permet de convertir un String en instance d'une classe numérique : Integer, Long, Float, Double
- FileEditor : capable de transformer un String en java.io.File
- InputStreamEditor : éditeur capable de prendre une chaîne de caractères afin de produire un objet InputStream.
- LocaleEditor : traduit un String en objet Locale. La chaîne de caractères traduites doit être au même format que celui que la classe Locale retourne dans sa méthode toString() ([langue]_[pays]_[variant])
- PatternEditor : crée des instances de la classe Pattern à partir d'un String
- PropertiesEditor : permet de transformer un String en instance de la classe Properties, en se basant sur le format défini pour la classe java.lang.Properties)
- StringTrimmerEditor : éditeur qui permet de supprimer les espaces blanches au début et à la fin d'une chaîne de caractères. Si le résultat est vide, le String peut être transformé en null
- URLEditor : transforme un String en l'instance de la classe URL

Utiliser les property editors dans Spring

Plusieurs méthodes de définir les property editor existent. Dans notre application de test on utilisera celle qui paraît la plus explicite. L'enregistrement des property editor se fera via l'annotation @InitBinder, comme le montre le code ci-dessous :

    @InitBinder
    public void bindForm(WebDataBinder binder) {
        binder.registerCustomEditor(List.class, "categoriesChecked", new BookCheckedPropertyEditor(List.class, BookCheckedPropertyEditor.TYPE_CATEGORIES));
        binder.registerCustomEditor(List.class, "writersChecked", new BookCheckedPropertyEditor(List.class, BookCheckedPropertyEditor.TYPE_WRITERS));
    }

@InitBinder est une annotation qui signale au Spring qu'une méthode doit être appelée avant l'appel de la méthode qui doit retourner le modèle de vue à l'utilisateur. Cependant, la méthode annotée avec @InitBinder sera appelée uniquement pour des méthodes qui contiennent des paramètres annotés avec @RequestMapping ou @ModelAttribute.

Illustrons ce propos avec un exemple. Imaginons qu'on a deux méthodes : bindData et createResponse. La première est annotée avec @InitBinder. La seconde retourne un String (modèle de vue) et prend comme paramètre un String annoté avec @RequestBody. La fonction définie au-dessous du @InitBinder sera alors utilisée ? Non, car createResponse n'est accompagné ni par @RequestMapping, ni par @ModelAttribute.

Cependant, dans certaines situations les éditeurs des propriétés doivent être enregistrés manuellement, via registerCustomEditor(). Cette opération s'applique à des données qui sont attachées au contrôleur grâce au DataBinder et validées avec un validateur personnalisé. Regardons cela sur le validateur de notre BookingController :

public class BookingController extends MainController {
    // ...
    public String doBookingHandle(@ModelAttribute("booking") Booking booking, @PathVariable long copy, 
    @LoggedUser AuthenticationFrontendUserDetails user, RedirectAttributes redAtt, HttpServletRequest request) {
        // ...
        // make some validation before and add property editor for date field
        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));
        binder.validate();
        // ...
    }
}

Rajouter des property editors dans Spring

Le grand avantage du Spring ne nous permet pas de se limiter à des fonctionnalités qu'il offre. C'est pourquoi on a décidé d'implémenter certains éditeurs supplémentaires dans notre application d'exemple. Dans cet article on présentera BookCheckedPropertyEditor<T> qui hérite de CustomCollectionEditor :

afficher le code

La conversion ci-dessus se fait sur la base du code du constructeur défini dans le 2e paragraphe (BookCheckedPropertyEditor<Category>(List.class, BookCheckedPropertyEditor.TYPE_CATEGORIES)). En ce qui concerne le code du property editor, il possède la méthode setAsText dont le rôle est de transformer une chaîne de caractères en élément de la collection.

Conversion service ou property editor ?

Jusque là on a vu 2 façons de transformer les objets : via conversion service ou via property editor. Les deux se ressemblent et parfois il peut s'avérer difficile de faire un jugement et utiliser le convertisseur adapté à la situation. Quand on devrait utiliser l'un et quand l'autre ?

Property editor est principalement destiné à faciliter la communication entre Spring et l'API Servlet, c'est-à-dire à effectuer les transformations entre String et Object. Il sera donc utilisé dans tout traitement des données provenant de la couche vue (formulaires, paramètres des URL), qui sont fournies au Spring en tant que chaînes de caractères.

En ce qui concerne conversion service, il est plus généraliste. Il permet d'effectuer tous les types de conversions (à partir du String, mais aussi à partir d'un Integer ou autre). Conversion service peut donc substituer au property editor. Cependant, l'inverse peut se produire uniquement dans le cas de conversion d'une chaîne de caractères.

// TODO : aborder d'autres méthodes d'enregistrement des property editors

Une question ? Une remarque ?

*

*

Un conseil Android

Comment accéder au localhost ?

A la place de 127.0.0.1 il faut utiliser 10.0.2.2.