20090922: Chti'JUG Hibernate Search & JSR303

Ma première soirée au Chti'JUG, dans les locaux de Norsys en plus! Je ne pouvais manquer cela. Il y avait du monde, probablement une petite centaine de personnes, la pompe à bière était prête, le soleil s'était mis de la partie ce qui n'était pas nécessairement une bonne idée compte-tenu de la disposition des locaux: la présentation se déroulait dans l'atrium, sous une verrière.

La présentation a commencé avec une demi-heure de retard: 19h au lieu des 18h30 prévues, ce qui est un peu regrettable, en particulier pour ceux qui ont la chance d'avoir une vie de famille et de travailler sur Paris. Denis Cassoret a fait une introduction rapide, mentionnant au passage l'Agile Tour à Lille puis a laissé la parole à Emmanuel Bernard, de JBoss, développeur d'Hibernate, venu nous parler de deux sujets: la mise en place de règles déclaratives de validation de contenus des JavaBeans (aka. JSR303 pour les intimes) et l'utilisation de la recherche plein texte avec Hibernate Search.

Quelques commentaires sur la forme:

JSR-303

La JSR303 offre un moyen de déclarer des contraintes sur les attributs d'un graphe d'objets au moyen d'annotations. Ces annotations sont récupérables dynamiquement (API java.lang.annotations.) ou statiquement (javax.lang.) au moyen d'apt, l'outil de traitement des annotations fourni dans le JDK. La JSR prévoit que divers frameworks et outils peuvent utiliser ces annotations pour déclencher la validation des attributs correspondant à l'exécution et ce dans différentes couches du système. L'objectif est bien sûr de pouvoir définir un seul modèle-métier susceptible d'être réutiliser de bout en bout, au besoin par génération de code, intercepteurs, ponts et autres adaptateurs...

Les annotations représentant des contraintes peuvent être composées par héritage et surannotation (une annotation sur une annotation), et il aussi possible de définir ses propres validateurs sur des types généraux ou spécifiques. L'ensemble utilise les possibilité nouvelles (!!) de Java 5: types génériques, APT, réflexion étendue... Une possibilité semble-t'il intéressante consiste à pouvoir grouper les contraintes voire à définir des séquences de groupes, l'idée étant que certaines validations seront pertinentes dans un certain contexte seulement, par exemple une pré-commande n'aura pas les mêmes contraintes qu'une commande ferme.  

Parmi les autres caractéristiques de cette norme, on trouve pêle-mêle la généralisation de l'utilisation d'interfaces fluides (fluent interface dans la langue de Britney Spears), les possibilités de paramétrage (i18n) des messages d'erreurs, une API offrant des méta-données sur les annotations de contraintes à l'usage d'outils divers et variés. Le moteur proposé par Hibernate (l'implémentation de référence semble-t'il) intègre directement le framework dans les Java Server Faces 2 et Java Persistence API 2. Enfin, les validateurs peuvent être injectés en Java EE 6 comme  des resources (@Resource).

Quelques questions posées:

Commentaires

En fait, ce dont on aurait vraiment envie, c'est de typer les attributs et objets au moyen de types métiers, sans nécessairement supporter le surcoût lié à l'encapsulation de types primitifs. Par exemple, au lieu de:


  @NotNull
  @Range(min="5", max="5")
  private String zipCode;
ou même previous

  @ZipCode
  private String zipCode;
on aimerait mieux: previous

  private ZipCode zipCode;

Hibernate search

La deuxième partie de la présentation est consacrée à Hibernate Search, c'est-à-dire à l'utilisation d'une recherche plein texte basée sur Lucene par dessus une couche Hibernate. Le principe est assez simple: on annote (une fois de plus) des attributs d'entités Hibernate afin de définir des modalités d'indexation de ces attributs. On a alors à sa disposition une API permettant de construire des requêtes basées sur des techniques de similarité de documents (ie. TF-IDF et co.) et utilisant ces index par l'intermédiaire de Lucene. LA valeur ajoutée d'Hibernate consiste à fournir une API orientée-métier, c'est-à-dire permettant de produire des objets métiers typés au lieu de documents génériques à la Lucene: on utilise la couche ORM pour reconstruire les objets à partir des données brutes de tables produites par le moteur d'indexation.

De très nombreuses possibilités sont offertes pour paramétrer d'une part le processus d'indexation et d'autre part le processus de recherche:

Sur le plan technique, on a aussi la possibilité de distribuer les index, de les cacher dans les divers niveaux de cache d'Hibernate, de les éclater (sharding). Une solution utilisant une mise à jour asynchrone de l'index par file JMS est même évoquée.

Conclusion

Une soirée sympathique et bien organisée, si l'on fait abstraction d'un horaire un peu fantaisiste :-) Je ne suis ni un spécialiste, ni un grand fan d'Hibernate ou plus généralement des ORM (en reste-t'il d'autre ?), mais le talent d'Emmanuel Bernard emporterait presque le morceau s'il n'y avait cette malencontreuse prolifération de symboles cryptiques induite par l'abus d'annotations, dans un langage  qui n'est déjà pas réputé pour être très lisible ni laconique. La lourdeur des annotations ne doit pas nous faire regretter la lourdeur encore plus pénible du XML, mais dans certains cas tel que celui de l'annotation de la classe entité par différents indexeurs où l'annotation prend 20 lignes, il y a de l'abus.

En fait, j'aimerais bien que les concepteurs d'API de ce type laissent le choix aux développeurs et proposent soit une API programmatique avec un système de types et de classes complet, éventuellement basé sur un MOP spécifique; soit des annotations. Un peu comme il est de bon ton quand on écrit une application d'offrir à la fois une interface graphique et une interface ligne de commande, quand bien même cette dernière serait-elle plus simple.