GitHub – Java & Moi https://javaetmoi.com Développeur Java, Spring & co, et fier de l'être Sat, 06 Nov 2021 17:04:16 +0000 fr-FR hourly 1 https://wordpress.org/?v=6.9.4 https://javaetmoi.com/wp-content/uploads/2022/05/cropped-java-icon-32x32.png GitHub – Java & Moi https://javaetmoi.com 32 32 18 prises de notes à Devoxx France 2019 https://javaetmoi.com/2019/05/18-prises-de-notes-a-devoxx-france-2019/ https://javaetmoi.com/2019/05/18-prises-de-notes-a-devoxx-france-2019/#respond Fri, 03 May 2019 17:28:03 +0000 https://javaetmoi.com/?p=1987 Continuer la lecture de 18 prises de notes à Devoxx France 2019 ]]> Ce fut ma 8ième participation à Devoxx France. Les années passent et je suis toujours aussi friand de cette bulle d’oxygène dans mon quotidien encore bien trop souvent parsemé de Struts, JSF et MagicDraw. Un grand bravo aux organisateurs, bénévoles et aux speakers.

D’ici quelques jours, l’intégralité des vidéos des conférences et universités présentées lors de Devoxx France 2019 sont disponibles sur la chaîne Devoxx FR de Youtube.

Si vous souhaitez rapidement vous faire un avis sur leur contenu avant de les visionner ou si vous souhaitez garder une trace écrite de ce que vous y avez appris, je mets librement à disposition l’ensemble de mes 18 notes prises au cours de ces 3 jours riches en contenus et en découvertes.

Lors de cette édition 2019, les 2 frameworks hypes du moment Quarkus et Micronaut étaient sur le devant de la scène en permettant de développer des applications Java modernes et natives grâce à GraalVM. Poussée par l’essor des microservices, l’intégration de Java à Docker et son orchestrateur Kubernetes est de plus en plus poussée. Les indémodables étaient également de la partie : design d’API REST, montée de version de Java, qualimétrie, JavaEE (oups, pardon, JakartaEE) et sécurité.

Mes notes classées par ordre de préférence :

  1. Quarkus : pourquoi et comment faire une appli Java Cloud Native avec Graal VM (Emmanuel Bernard et Clément Escoffier)
  2. D’architecte à Métarchitecte : une évolution nécessaire (Rémi Cocula)
  3. Construire son JDK en 10 étapes (José Paumard)
  4. Observabilité, Mythes, réalité et Chaos (Benjamin Gakic)
  5. Cycle de vie des applications dans Kubernetes (Charles Sabourdin et Jean-Christophe Sirot)
  6. Micronaut, le framework JVM ultra-light du futur (Olivier Revial)
  7. La gestion de l’authentification et de l’autorisation dans une architecture microservices ? Pas de soucis ! (Vivien Maleze et Florian Garcia)
  8. Du monolithe aux microservices chez leboncoin (Eric Lefevre-Ardant)
  9. Un turbo dans ton workflow GitHub (Alain Hélaïli)
  10. Sonar Smash (Helen Wallace et James Mac Mahon)
  11. De Java 8 à Java 11 sur un gros projet : les pièges à éviter (Alexis Dmytryk et Thomas Collignon)
  12. Oubliez Java EE, voilà Jakarta EE ! (Jean-François James et Sébastien Blanc)
  13. La JVM et Docker, vers une symbiose parfaite (Guillaume Scheibel)
  14. Migrer ses APIs vers GraphQL : pourquoi ? comment ! (Guillaume Scheibel)
  15. Au secours, mon projet BigData est en production! (Vincent Devillers)
  16. SpringBoot avec Kotlin, Kofu et les Coroutines (Sébastien Deleuze)
  17. 50 points de contrôle d’une API REST (François-Guillaume Ribreau)
  18. Dev environments: use the nix, Luke! (Clément Delafargue et Hussein Ait-Lahcen)

]]>
https://javaetmoi.com/2019/05/18-prises-de-notes-a-devoxx-france-2019/feed/ 0
Ma petite usine logicielle https://javaetmoi.com/2012/12/ma-petite-usine-logicielle-github-cloudbees/ https://javaetmoi.com/2012/12/ma-petite-usine-logicielle-github-cloudbees/#comments Sat, 15 Dec 2012 09:08:10 +0000 http://javaetmoi.com/?p=436 Continuer la lecture de Ma petite usine logicielle ]]> Suite à une question qui m’a récemment été posée sur Github, j’ai réalisé que ce que j’avais mis en place pour des besoins personnels pouvait intéresser d’autres développeurs.

Dans ce billet, je vais donc vous expliquer comment créer votre propre usine logicielle. Déployée à cheval sur GitHub et l’offre DEV@Cloud de CloudBees, vous y retrouverez les briques les plus classiques : SCM, intégration continue, dépôt de binaires, bug tracker, wiki …
Le gain : à chaque commit poussé dans GitHub, votre code est compilé, testé unitairement puis déployé dans un repository maven public dédié aux Snapshots. Par ailleurs, vous pourrez effectuer des releases maven en local depuis votre poste de développement ; les artefacts construits seront mis à disposition dans un repository maven dédié. Tout développeur pourra librement référencer l’un ou l’autre de ces repository et utiliser votre code.

En bonus, si vous développez des projets open source, vous n’aurez même pas à sortir votre carte bancaire.
cloudbees-github-jenkins

Composants de l’usine de développement

Le tableau ci-dessous liste les différentes briques de l’usine de développement ainsi que les motivations qui m’ont poussé à les choisir.

Brique de l’usine logicielle Outil Plateforme Raisons
Gestionnaire de Code Source (SCM) Git GitHub Pour utiliser la pleine puissance de Git, bridé jusque-là par l’utilisation en entreprise du bridge git-svn.
Outil de build Maven Poste de Dev
+ Cloudbees
L’incontournable maven.  Mais cela aurait pu être l’occasion de  tester Gradle.
Intégration Continue Jenkins CloudBees Un comble : probablement celui que je connaissais le moins par rapport à Continium, Bamboo et TeamCity.
Dépôt de binaires Repository Maven Cloudbees Offre de base de CloudBees suffisante.
Accès par webdav
Espace documentaire Wiki GitHub Pages versionnées avec Git
Syntaxte MarkDown
Le XWiki de CloudBees aurait pu être une alternative
BugTracker Navigateur Web GitHub Projets OSS personnels pas suffisamment actifs pour bénéficier d’un Jira (ni même d’une licence JRebel)

Afin de vous donner une idée du résultat, je vous invite à jeter un coup d’œil aux différentes URLs :

Pré-requis

2 prérequis sont nécessaires au déploiement d’une telle usine de développement :

  1. Disposer d’un compte GitHub et d’un repository contenant un projet java déjà mavenisé
  2. Avoir accès à la plateforme de build de CloudBees, soit en souscrivant à l’une des offres gratuites ou payantes, soit en souscrivant au Free FOSS Programm

Configuration Maven

Afin de pouvoir intégrer un projet mavenisé dans l’usine de développement, il est préalablement nécessaire de compléter sa configuration maven pour prendre en compte :

  • Le gestionnaire de code source pour que maven ait accès en lecture / écriture au repository git distant (hébergé ici sur GitHub), ce qui est par exemple nécessaire pour tagger et faire des releases maven.
  • Les repository maven des releases et des snapshots, ce qui est utile à Jenkins ou au plugin release de maven pour déployer un artefact, et par maven pour télécharger des artefacts.
  • La configuration de l’extension maven wagon-webdav, utile lors du déploiement d’un artefact sur le repo maven CloudBees utilisant le protocole webdav.
  • Les credentials d’accès en écriture au webdav, là encore utile pendant la phase de déploiement d’un artefact.

Toute cette configuration est détaillée dans un précédent billet intitulé Release Maven sous Windows d’un projet GitHub déployé sur CloudBees. Vous y trouverez notamment comment configurer les différentes balises maven au travers 2 fichiers :

  • pom.xml : <scm>, <distributionManagement>, <repositories> et <extensions>
  • settings.xml : <servers>

Gage de son intérêt, le projet github maven-config-github-cloudbees à l’origine de l’article a été forké par Ryan Cambell et est désormais proposé dans la Cloudbees Community de GitHub.

Une fois le pom.xml commité dans GitHub avec le reste du code source, le build Jenkins correspondant peut être configuré.

Configuration Jenkins

Depuis la console d’administration de Jenkins, vérifier que le Jenkins GIT plugin soit installé puis installer le GitHub plugin.

Dans la section CloudBees DEV@Cloud Authorization, configurer l’URL du chemin d’accès au repository Github qui sera utilisée par le plugin GitHub:

cloudbees-build-authorization

Dans la section Gestion de code source du build Jenkins, sélectionner l’option Git Repositories puis renseigner le Repository URL.
La syntaxe à utiliser est la suivante : https://github.com/<username>/<repository name>.git
Exemple : https://github.com/arey/hibernate-hydrate.git
cloudbees-build-git

Afin que Jenkins lance le build lors de la réception d’un hook en provenance de GitHub, sélectionner la case Build when a change is pushed to GitHub dans le panneau ci-dessous :
cloudbees-jenkins-build-trigger

La version de maven, le chemin vers le pom.xml racine ainsi que le goal à exécuter peuvent être configurés dans la section Build :
cloudbees-jenkins-maven
Lorsqu’aucun goal n’est précisé, Jenkins exécute un install.

A la fin du build, on indique à Jenkins de déployer les artefacts dans le repository CloudBees des Snapshots :
cloudbees-jenkins-deploy

Afin d’exploiter au mieux le plugin GitHub de Jenkins et laisser Jenkins configurer les hooks dans GitHub, il est possible de renseigner votre login / mot de passe dans l’encart GitHub Web Hook accessible depuis le menu Administration Jenkins > Configurer le Système.
cloudbees-jenkins-github-web-hook

Dernière étape de la mise en place de notre usine de développement : la configuration de GitHub.

Configuration GitHub

Pour que Jenkins soit notifié à chaque push dans GitHub et relancer ainsi le build maven configuré précédemment, il est nécessaire de configurer un Hook web dans GitHub.
La WebHook URL doit référencer votre forge  logicielle CloudBees.
Syntaxe : https://<cloudbees username>.ci.cloudbees.com/github-webhook/
Exemple : https://javaetmoi.ci.cloudbees.com/github-webhook/
github-webhook-cloudbees
Cette configuration n’est a priori pas nécessaire si vous utilisez le plugin GitHub Jenkins. Ce dernier se charge en effet d’ajouter les WebHooks pour vous.

Pour que CloudBees ait les habilitations nécessaires pour accéder à l’ensemble de vos repository GitHub, sa clé publique doit être ajoutée dans la partie SSH Keys accessible via le menu d’administration de GitHub :
github-ssh-keys

En principe, si je n’ai rien omis de mentionner dans ce guide, tout est prêt. Et pour vérifier que votre usine de développement est opérationnelle, vous avez le choix entre :

  1. pousser une modification dans votre repository GitHub
  2. ou simuler un hook depuis GitHub.

Conclusion

Suivant CloudBees depuis son lancement il y’a plus de 2 ans, j’ai eu la chance de pouvoir bénéficier début 2012 de l’offre gratuite Free and Open-Source Software. Après avoir passé un peu de temps au départ pour mettre en place mon usine, j’en suis aujourd’hui pleinement satisfait et je serais prêt à l’expérimenter en entreprise.

N’ayant utilisé qu’une infime partie des services proposés par CloudBees, de nombreuses découvertes s’offrent encore à moi : utiliser le plugin release de Jenkins, tester SauceLabs ou bien encore déployer une application web sur la plateforme RUN@CloudBees.

Apparu quelques mois après mes débuts sur DEV@cloud, CloudBees propose le produit BuildHive aux développeurs utilisant GitHub et qui souhaitent mettre en place de l’intégration continue sur leur projet. Non seulement ce produit est gratuit, mais il simplifie considérablement la configuration de votre build, à la fois côté Jenkins que côté GitHub grâce au protocole OAuth. Tout est automatisé. Je me suis inscrit et j’ai créé mon premier build en à peine 2 minutes. Un hook sur les pull request permet même de lancer un build afin de valider le code soumis. Néanmoins, il y’a tout de même quelques limitations par rapport à la solution que vous ai proposée : pas de repository maven, impossibilité d’installer des plugins Jenkins … A vous de décider lequel vous convient !

]]>
https://javaetmoi.com/2012/12/ma-petite-usine-logicielle-github-cloudbees/feed/ 1
Release Maven sous Windows d’un projet GitHub déployé sur CloudBees https://javaetmoi.com/2012/04/release-maven-windows-github-deploy-cloudbees/ https://javaetmoi.com/2012/04/release-maven-windows-github-deploy-cloudbees/#respond Thu, 12 Apr 2012 19:42:24 +0000 http://javaetmoi.com/?p=81 Continuer la lecture de Release Maven sous Windows d’un projet GitHub déployé sur CloudBees ]]> logo_githubHabitué aux releases maven avec SVN, j’ai rencontré quelques difficultés pour effectuer la première release du projet Hibernate Hydrate [1] hébergé sur GitHub et présenté dans un précédent billet.

Pour rappel, lors d’une release, le plugin maven accède au gestionnaire de code source pour commiter les modifications effectuées sur les pom.xml et créer un tag. Il déploie ensuite les artefacts sur le repo maven distant.

Mes contraintess techniques étaient les suivantes :

  • Plateforme de développement : Windows 7, JDK 6, mSysGit
  • Code source Java mavenisé et hébergé sur GitHub
  • Le repo maven sur lequel déployer les artefacts maven est hébergé par CloudBees et accessible par le protocople Webdav [2]

Les réponses apportées par ce billet sont :

  1. Configuration maven pour GitHub
  2. Problème de passphrase SSH spécifique à Windows
  3. Configuration maven du repo CloudBees

Configuration maven pour GitHub

Pour permettre à maven d’accéder en lecture et en écriture à votre repo GitHub, vous devez tout d’abord configurer comme suit la balise <scm> de votre pom.xml :

<scm>
<url>https://github.com/arey/maven-config-github-cloudbees</url>
<connection>scm:git:ssh://[email protected]/arey/maven-config-github-cloudbees.git</connection>
<developerConnection>scm:git:ssh://[email protected]/arey/maven-config-github-cloudbees.git</developerConnection>
</scm>

L’accès en écriture sur un repo GitHub requière l’utilisation du protocole SSH. L’URL est conforme à ce qui est spécifié dans la documentation de référence maven [3] :

scm:git:ssh://server_name[:port]/path_to_repository

A noter une syntaxe légèrement différent au chemin SSH affiché sur GitHub : /arey et non :arey, le caractère : étant utilisé pour préciser le port de connexion.

URL SSH de GitHub

Pour tester la configuration maven, vous pouvez par exemple utiliser le plugin scm pour créer un tag. C’est ce plugin qui est utilisé par le plugin release.

mvn org.apache.maven.plugins:maven-scm-plugin:1.6:tag -Dtag=test -Dbasedir=.

Vous devriez obtenir les logs suivants :

[INFO] --- maven-scm-plugin:1.6:tag (default-cli) @ maven-config-github-cloudbees ---
[INFO] Final Tag Name: 'test'
[INFO] Executing: cmd.exe /X /C "git tag -F D:\tmp\maven-scm-1264232534.commit test"
[INFO] Working directory: D:\dev\workspaces\WS_GitHub\maven-config-github-cloudbees
[INFO] Executing: cmd.exe /X /C "git push ssh://[email protected]/arey/maven-config-github-cloudbees.git test"
[INFO] Working directory: D:\dev\workspaces\WS_GitHub\maven-config-github-cloudbees

1 minute. 2 minutes. Le plugin s’arrête là, comme bloqué. L’occupation CPU est à 0%. Ne cherchez pas, vous êtes sous Windows.

Problème SSH spécifique à Windows

En interne, le plugin scm exécute des lignes de commandes git.
Sous Windows, la ligne de commande git est exécutée par l’interpréteur de commandes cmd.exe en mode non interactif.
Or, lorsque vous essayez manuellement de pousser vos modifications vers GitHub depuis un bash git ou une ligne de commande avec git dans le path, Git vous demande systématiquement votre passphrase :

git push
Enter passphrase for key '/c/Users/Antoine/.ssh/id_rsa':

L’explication est là : lors d’un tag ou d’un push, le plugin scm est bloqué car il attend votre passphrase. Pour autant, il ne vous demande jamais de le saisir. Vous vous retrouvez bloqué.

L’une des solutions permettant de résoudre ce problème est de répondre à la question : « Comment faire pour que Windows retienne ma passphrase ? »  Stackoverflow.com vous donne la réponse [4].

En résumé, vous allez demander à git d’utiliser PuTTY pour communiquer en SSH avec GitHub. L’agent d’authentification SSH Pageant sera utilisé pour conserver votre clés privée Github en mémoire pour que vous puissiez vous authentifier sans avoir besoin de retaper votre phrase de passe à chaque fois. Voici le mode opératoire :

  1. Télécharger puis décompresser l’archive putty.zip librement téléchargeable depuis le site de Putty [5].
  2. Utiliser PuTTYGen.exe [6] pour convertir au format PuTTY (.ppk) votre clé RSA GitHub généré avec open SSH.
  3. Exécuter pageant.exe [7], ajouter la clé au format PuTTY and saisir le passphrase
  4. Déclarer la variable d’environnement GIT_SSH en spécifiant le chemin vers plink.exe [8], outil de connexion en ligne de commande utilisé pour automatiser des connexions.

Pour tester la configuration, ouvrir une nouvelle fenêtre de commande et exécuter la commande suivante :

C:\Software\Dev\Putty>plink.exe [email protected]
Using username "git".
Server refused to allocate pty
Hi arey! You've successfully authenticated, but GitHub does not provide shell access.

La création d’un tag par le plugin scm de maven doit désormais aboutir.

Configuration des repository Cloudbees

Avant de pouvoir effectuer une release, il est encore nécessaire de configurer les repository maven de votre forge CloudBees. Il s’agit ici de configuration maven relativement ordinaire.

Lors de la phase de déploiement d’un artefact, 2 repositories sont nécessaires, l’un pour déployer des releases,et  l’autre pour déployer des snapshots :

<distributionManagement>
    <downloadUrl>https://github.com/arey/maven-config-github-cloudbee</downloadUrl>
    <repository>
      <id>javaetmoi-cloudbees-release</id>
      <name>javaetmoi-cloudbees-release</name>
      <url>dav:https://repository-javaetmoi.forge.cloudbees.com/release/</url>
    </repository>
    <snapshotRepository>
      <id>javaetmoi-cloudbees-snapshot</id>
      <name>javaetmoi-cloudbees-snapshot</name>
      <url>dav:https://repository-javaetmoi.forge.cloudbees.com/snapshot/</url>
    </snapshotRepository>
 </distributionManagement>

Point d’attention : les repositories CloudBees ne sont accessibles en écriture que par le prococole WebDAV. Les URL des repository doivent donc être préfixées par un dav:

L’extension maven wagon-webddav est requis pour que maven puisse interprêtrer le dav:.  A ajouter dans la balise <build> de votre configuration :

<extensions>
    <extension>
        <groupId>org.apache.maven.wagon</groupId>
        <artifactId>wagon-webdav</artifactId>
        <version>1.0-beta-2</version>
    </extension>
</extensions>

Afin que maven puisse accéder à ces repository pour télécharger les snapshots et les releases, il est nécessaire de les déclarer, soit dans le pom.xml de votre projet, soit dans le fichier setting.xml global ou local à l’utilisateur (ce qui est une bien meilleure pratique) :

<repositories>
    <repository>
      <id>javaetmoi-cloudbees-release</id>
      <name>javaetmoi-cloudbees-release</name>
      <url>https://repository-javaetmoi.forge.cloudbees.com/release/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>javaetmoi-cloudbees-snapshot</id>
      <name>javaetmoi-cloudbees-snapshot</name>
      <url>https://repository-javaetmoi.forge.cloudbees.com/snapshot/</url>
      <releases>
        <enabled>false</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
  </repositories>

Lors d’un déploiement distant (ex : mvn deploy), maven doit disposer des paramètres de connexion pour écrire dans l’un ou l’autre des repository. A configurer dans le fichier setting.xml global ou local de l’utilisateur :

<servers>
    <server>
      <id>javaetmoi-cloudbees-snapshot</id>
      <username>javaetmoi</username>
      <password>Mot de passe CloudBees</password>
    </server>
    <server>
      <id>javaetmoi-cloudbees-release</id>
      <username>javaetmoi</username>
      <password>Mot de passe CloudBees </password>
</server>

 

Attention, bien que le mot de passe soit celui que vous utilisez pour vous connecter à vore compte CloudBees, le username ne correspond pas à votre adresse email, mais celui spécifié dans la forge CloudBees comme le montre la capture d’écran ci-contre.

Pour figer sa version, le plugin maven release peut également être déclaré dans votre pom.xml :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-release-plugin</artifactId>
    <version>2.2.2</version>
</plugin>

Ca y’est, toute la configuration est en place. A vous de jouer :

mvn release:prepare release:perform

Conclusion

Afin d’avoir sous la main un squelette pour un prochain projet, j’ai initié un projet GitHub regroupant toute la configuration maven nécessaire : https://github.com/arey/maven-config-github-cloudbees [9]. Vous pouvez y télécharger l’intégralité du pom.xml et du settings.xml décrits dans cet article]. Ce projet a fait des émules puisque le code a été forké par la CloudBees-Community [10] de Github.

Pour ne plus avoir besoin à configurer PuTTY, un axe d’amélioration du plugin release serait de pouvoir s’appuyer un provider Git en full java, basé par exemple sur JGit [11] (projet utilisé par le plugin Eclipse EGit).  Initié par Olivier Lamy, le projet maven-scm-provider-jgit [12] semble malheureusement s’être arrêté avant que jgit ne bascule sous le giron de la fondation Eclipse. Avis aux contributeurs !!

Références :

  1. Projet Hibernate Hydrate hébergé sur Github
  2. Définition du protocole WebDAV sur Wikipédia
  3. Apache Maven SCM Git Implementation dans la documentation de référence maven
  4. Why git can’t remembrer my passphrase under Windows sur stackoverflow.com
  5. Télechargement de PuTTY
  6. Manuel utilisateur de PuTTYgen
  7. Manuel utilisateur de Pageant
  8. Manuel utilisateur de plink
  9. Projet Maven Config  pour GitHub & CloudBees hébergé sur GitHub
  10. Communauté CloudBees sur GitHub
  11. Site officiel du projet JGit hébergé sur Eclipse.org
  12. Site officiel du projet maven-scm-provider-jgit hébergé sur Google Code
]]>
https://javaetmoi.com/2012/04/release-maven-windows-github-deploy-cloudbees/feed/ 0
Dites adieu aux LazyInitializationException https://javaetmoi.com/2012/03/hibernate-dites-adieu-aux-lazy-initialization-exception/ https://javaetmoi.com/2012/03/hibernate-dites-adieu-aux-lazy-initialization-exception/#comments Fri, 30 Mar 2012 20:39:43 +0000 http://javaetmoi.com/?p=54 Continuer la lecture de Dites adieu aux LazyInitializationException ]]>
logo_hibernate

Dans ce deuxième ticket, j’aimerais vous parler du projet Hibernate Hydrate [1] que j’ai récemment publié sur GitHub. Au cœur de ce projet : une seule classe Java proposant une unique fonctionnalité. En quelques années, c’est la seconde fois que j’ai eu besoin de coder ce genre de fonctionnalité. Aussi, je me suis dit qu’il serait pratique de l’avoir sous le coude pour une prochaine fois et, au passage, vous en faire profiter.

Origine des lazy exceptions

En quoi consistent ce projet et cette fameuse fonctionnalité ? Eh bien, sous certaines conditions, résoudre un problème récurrent lors de l’utilisation d’Hibernate. En effet, lorsque l’on tente d’accéder à un objet détaché de la session Hibernate, ce dernier n’est pas forcément entièrement chargé en mémoire : son proxy ou ses propriétés peuvent ne pas être initialisés, ce qui est par exemple le cas d’une relation déclarée comme paresseuse (ou lazy). Et c’est à cet instant-là, qu’Hibernate lève la tant redoutée LazyInitializationException.
Par objet détaché, j’entends un objet évincé de la session (retirée du cache de premier niveau par un session.clear() ou un evict()) ou dont la session est fermée (session.close())
Dans une application, ce phénomène est susceptible de se produire à plusieurs niveaux :

  • Couche présentation : contrôleur (ex : action Struts) ou rendu de la vue (ex : JSP)
  • Exposition d’un web service : marshalling XML, mapping dozer …

La documentation d’Hibernate propose plusieurs solutions pour remédier à ce problème. Plus encore, elle explique ce qu’il faut éviter de faire, comme par exemple ouvrir une autre unité de travail (transaction) pour charger les données manquantes.
Solutions préconisées

Pattern Open Session In View

Une première solution consiste à utiliser le pattern Open Session In View [2]. Dans une application web, ce pattern peut par exemple être implémenté à l’aide d’un filtre de servlets. L’arrivée d’une requête HTTP initie l’ouverture d’une transaction et de la session Hibernate correspondante. Une fois la vue rendue et prête être renvoyée au client, la session est fermée et la transaction est validée.
Le pattern Open Session In View ne peut pas s’appliquer dans une architecture technique 3 tiers où la couche présentation et la couche métier sont déployées physiquement sur 2 serveurs différents, et donc 2 JVMs. Ce pattern n’est également pas valable dans le cadre d’une application web riche utilisant Ajax et JavaScript pour récupérer puis parcourir le modèle métier.

Pré-chargement sur mesure

Personnellement, je recommande généralement à ce que les transactions soient gérées au niveau de la couche métier. En effet, à ce niveau, le service métier connait l’usage des objets qu’il va charger depuis la base de données. Il est capable d’utiliser le DAO ayant la stratégie de pré-chargement [3] (ou fetching) adaptée au traitement métier.

Pour rappel, le pré-chargement des relations peut être configuré de 2 manières :

  1. statiquement au niveau du mapping Hibernate (en XML ou par annotations)
  2. dynamiquement lors du requêtage en HQL (JOIN FETCH) ou par l’API Criteria (méthode setFetchMode())

Par défaut, dans Hibernate 3.x, les associations vers une autre entité ou une collection d’entités sont chargées tardivement ; c’est-à-dire à la demande, lorsque l’on essaie d’accéder à l’entité ou à la collection (et que la session est ouverte). Qui plus est, les stratégies définies statiquement ne sont pas forcément utilisées lors d’un requêtage HQL.

Une bonne pratique issue du guide de référence d’Hibernate [4] consiste à conserver le comportement par défaut d’Hibernate et à redéfinir la stratégie de pré-chargement à chaque usage. Cela permet d’optimiser votre code et de ramener les données dont vous avez strictement besoin.

Comme illustré dans l’article Hibernate Survival Guide [5], et grâce au cache de premier niveau d’Hibernate, il est parfois plus performant de découper sa requête en plusieurs requêtes, notamment lorsque la grappe d’objets est complexe et la cardinalité des associations importante.


Hybernate Hydrate à la rescousse

La solution que je vais vous présenter peut être utilisée conjointement avec la solution du pré-chargement sur mesure.

La méthode statique deepHydrate de la classe LazyLoadingUtil permet de charger dans sa globalité la grappe d’objets qui lui est passée en paramètre. Seule contrainte, cette méthode doit être appelée avant que la session Hibernate et la transaction associée ne soient clôturées.

Voici un exemple d’utilisation :

Employee employee = (Employee) session.get(Employee.class, 1);
LazyLoadingUtil.deepHydrate(session, employee);

Techniquement, la méthode deepHydrate() utilise le méta-modèle Hibernate (interface ClassMetadata) pour parcourir l’ensemble du graphe des objets persistés et déterminer le type des propriétés et des relations du modèle. Ainsi, elle peut naviguer récursivement dans le graphe. Les proxy rencontrés sont initialisés puis résolus. Les collections persistantes sont initialisés puis itérés.

Dans le cas d’un graphe cyclique, un mécanisme de garde permet d’éviter toute boucle infinie.

La classe TestLazyLoadingUtil propose des exemples d’utilisation.

Une variante est disponible pour les applications utilisant JPA avec Hibernate pour provider : JpaLazyLoadingUtil.

Pour l’essayer, vous avez le choix entre un copier / coller, un git clone ou bien l’ajout d’une dépendance maven et du repo qui va avec :

<dependency>
    <groupId>com.javaetmoi.core</groupId>
    <artifactId>javaetmoi-hibernate4-hydrate</artifactId>
    <version>2.0</version>
</dependency>

Les artefacts du projet Hybernate Hydrate sont disponibles sur Maven Central.

Conclusion

Pour terminer cette présentation, voici un tableau récapitulatif qui devrait vous permettre d’orienter votre choix sur l’usage ou non de cette petite librairie :

Scénarios pour lesquels écarter cette solutionScénarios favorables à son utilisation
  1. Utilisation du pattern Open Session in View
  2. Problématiques fortes de performance
  3. Grappes d’objets risquant de remonter toute la base de données
  1. Grappe d’objets constituée de nombreuses classes
  2. Développement rapide d’une application avec chantier d’optimisations portant sur les requêtes critiques
  3. Exploitation du cache de niveau 2 d’Hibernate pour les données en « bout de grappe » (ex : données du référentiel).
  4. Outil ayant besoin de charger toute une grappe d’objets en mémoire

De mon côté, ce modeste travail de capitalisation m’a permis de renouer avec l’open-source ;  en tant que contributeur j’entends. Mon dernier code poussé sur Source Forge datait en effet de l’an 2000 …
Cela m’aura également permis de me familiariser davantage avec GitHub : syntaxe MarkDown, pages wiki gérées par git ou bien encore les releases avec maven. Ce dernier point fera d’ailleurs l’objet d’un prochain article.
J’ai également pu adhérer au programme Free and OpenSource (FOSS) de CloudBees, ce qui vous permet d’accéder librement au Jenkins d’Hibernate Hydrate [6].

Enfin, si vous êtes un jour amené à utiliser ce code, je serais intéressé de le savoir. Et si vous voulez contribuer (ex : support d’autres ORM, annotation + post-processeur Spring …), les portes sont grandes ouvertes.

Références :

  1. Projet Hibernate Hydrate hébergé sur Github
  2. Open Session In View du wiki Hibernate de JBoss
  3. A Short Primer On Fetching Strategies du wiki Hibernate de JBoss
  4. Performance fetching du guide de référence d’Hibernate
  5. Hibernate Survival Guide du wiki d’Object Direct
  6. Jenkins d’Hibernate Hydrate hébergé sur la plateforme DEV@Cloud de CloudBees[6].
]]>
https://javaetmoi.com/2012/03/hibernate-dites-adieu-aux-lazy-initialization-exception/feed/ 4