Archives de Catégorie: JBoss

Spring Boot

J’utilise Spring depuis maintenant 3 ans (depuis ma formation en DIF en fait) et en voulant moderniser nos sites web écrit en Spring 3.x je suis tombé sur le projet Spring Boot.

Le principe premier de Spring Boot est de pouvoir démarrer un projet en quelques lignes de code … avec Spring. Il y a même eu un tweet (donc maximum 140 caractères) qui est un code pouvant lancer un serveur web et répondre sur une URL. De la même façon une API Rest minimaliste pourrait donc aussi tenir dans un tweet.

Note à part : si vous connaissez node.js cela ne vous rappelle rien ? On dirait que Spring Boot est une réponse au succès de node.js et à la création « les doigts dans le nez » d’un site web ou d’une API Rest en un rien de temps. Spring Boot permet même de lancer une ligne de commande un serveur web exécutant un code minimaliste ou de créer un livrable prêt à lancer un serveur web en production. Spring Boot s’inscrit dans le la notion de RAD dans l’univers web.

Pourquoi Spring Boot et non simplement Spring (ou Spring MVC pour un site web) ? A cause de la configuration … Spring est très bien pour délivrer des petits bouts fonctionnels mais l’agglomération de tout ces petits bouts est couteux. Là où intervient Spring Boot est qu’il détecte ces petits bouts et les configurent au mieux que possible.

Mais comment les détecte t-il ? Via les librairies présentent dans le classpath ! Par exemple si dans votre projet vous mettez (comme moi) la librairie freemarker alors il se dit qu’il faut configurer Spring MVC afin qu’il puisse utiliser des templates freemarker et que ces mêmes templates sont dans /templates/ (vis à vis du classpath).

Mais, n’est-il pas trop « aggressif » dans sa manière de fonctionner ? Oui et non. C’est vrai que du coup Spring Boot est très ce qu’on appelle « opinionated » (terme très en vogue dans les framework web) c’est-à-dire qu’il gère les composants de la manière qu’il lui semble optimale mais sans que ce soit à votre manière. Cependant sa philosophie c’est d’être « opinionated » mais de pouvoir à tout moment prendre le dessus (la philosophie première de Spring en fait). Et justement il facilite la prise en main d’une fonctionnalité particulière.

Donc en clair il suffit de créer un projet Maven en déclarant que le pom parent est spring-boot-starter-parent et de choisir une dépendance avec un « starter » et hop … il suffit de créer un contrôleur comme le tweet ci-dessus puis de faire un

> mvn spring-boot:run

et on a un site web fonctionnel !

(cela peut aussi être fait avec Gradle, c’est selon l’environnement de travail)

Bon Spring Boot n’est pas que cela il y a de nombreuses autres fonctionnalités que vous pourrez consulter dans la documentation de Spring Boot.

Je dois quand même avouer, avec mon expérience de Spring, qu’il s’agit d’une facilité bienvenue. Combien de fois ais-je dû me demander commander intégrer tel ou tel composant dans Spring ?

Et puis pour aller encore plus loin, Spring Boot est assez bien intégré avec le Cloud. Donc, par exemple, développer une API Rest sur Heroku est « assez rapide ». Spring Boot donne toutes les instructions nécessaires pour un déploiement dans le cloud via les acteurs majeurs de la place. Voir içi (tiens d’ailleurs Google Application Engine n’est qu’en version Servlet 2.5 !).

Pour bien commencer avec Spring Boot et en français voici un article intéressant.

Alors en conclusion je dirais que Spring Boot est très intéressant surtout pour démarrer rapidement un projet (web/rest/batch/etc…) MAIS la contremesure c’est d’apprendre une surcouche de Spring (Spring Boot) en plus de Spring lui-même. Il y a de nouvelles annotations, de nouvelles classes, de nouvelles librairies, de nouvelles façon de faire mais il faut quand même connaître Spring pour, au fur à mesure, aller plus loin dans le développement. A coté il y a Java EE 7 … (que j’utilise déjà pour d’autres briques de notre système d’information). Quand je regarde le code de spring-boot-*.jar  (notamment spring-boot-autoconfigure-*.jar) je me dis que ce n’est plus la même manière de fonctionner qu’auparavant. Mais après tout Spring Boot est pour nous aider à démarrer un projet et non nous contraindre sur l’apprentissage de nouvelles annotations.

Dernier point (oui encore un) j’ai une appréhension sur la manière dont Spring Boot fonctionne : il analyse le classpath à la recherche de librairies (en faite de classes) permettant de déclencher certaines fonctionnalités (tiens au fait Java EE ne fait pas déjà cela ?). Cependant cette même gestion de classpath au sein de Java est problématique car non adaptée (à mon sens) à une gestion moderne de librairies. Je fais en fait référence à la JSR 277 (Java Module System) qui devrait modulariser Java mais qui est en cesse repousée (Java 9 ou Java 10 ?). Cela aura un impact assez lourd sur le ClassLoader de Java et du coup, par rebond, à Spring Boot.

Et puis aussi avec ce dernier point je dois préciser que j’utilise dès que je peux JBoss AS 7 / WildFly 8.1. Je trouve que c’est un superbe serveur d’application et le serveur web n’est plus tomcat (sur WildFly) mais Undertow que est extra-performant et fait partie des meilleurs serveurs mondiaux (par exemple, attention je suis conscient que cela dépend de beaucoup de paramètres et que node.js peut être plus performant, ou même d’autres !). Et concernant Sprint Boot cela fonctionne sous WildFly mais sous peu que TOUTES les librairies soient dans le WAR lui-même. Le problème ? C’est j’aime bien mettre les librairies sous forme de modules dans JBoss AS 7 / WildFly MAIS que du coup la gestion des classes de ces modules n’est pas celle attendue par Spring Boot et donc aucune fonctionnalité mise en module n’est détectée. Pourtant j’ai insisté pendant plusieurs jours (voir nuits) mais impossible à faire détecter les modules par Spring Boot (pour l’auto configuration) … J’en suis arrivé à la conclusion que Spring Boot fonctionne sous JBoss AS 7 / Wild Fly mais que toute librairie nécessaire doit être dans le WAR et que tout module ne sera pas détecté pour être auto-configuré. Donc retour aux FAT-WAR(s) que je déteste tant … ou alors je continue d’utiliser Spring en mode classique, à voir.

Migration : JBoss AS 7.1.1 vers JBoss EAP 6.3

Jusqu’à maintenant nous utilisions JBoss AS 7.1.1 qui est la dernière version communautaire disponible. Deux ans plus tard et même si cette version fonctionne plutôt bien ses modules ne sont pas des plus récents (Hibernate / RestEasy / etc) et il a été reconnu que JBoss AS 7.1.1 possède quelques bugs qui ne seront jamais résolu en tant que JBoss AS.

Pour migrer vers un serveur plus récent il y a eu deux choix : soit migrer vers une version dite « EAP » (Enterprise Application Platform ») qui est une version dite d’entreprise car elle possède un support (payant) de la part de RedHat soit directement migrer vers WildFly 8 qui est en fait JBoss AS 8 mais renommé car « JBoss » était devenu un terme trop générique (voir la page de Wikipedia pour plus d’information sur ce sujet).

Cependant WildFly 8 étant un gap technique assez important ce fut plutôt JBoss EAP 6.3.0.GA qui fut choisi. Ce dernier est équivalent à un JBoss 7.4.x et possède quasiment toutes les caractéristiques techniques de JBoss AS 7.1.1. Cela fut donc assez rapide, modulo de devoir retester toutes les applications (environ une dizaine, argh) et de vérifier que la remontée des stats fonctionne toujours (projet interne faisant de l’introspection de Tomcat pour remonter des métriques).

Donc au menu il y a eu les problèmes suivants :

  • Hibernate affichait beaucoup trop de traces. Corrigé avec la liste suivante dans tous les fichiers persistence.xml :
<property name="hibernate.session.events.log" value="false" />
  • Les datasources ne détectaient pas les pertes de connexion. Corrigé dans le fichier standalone.xml en remplaçant :
<validation>
    <check-valid-connection-sql>select 1</check-valid-connection-sql>
    <validate-on-match>false</validate-on-match>
    <background-validation>false</background-validation>
    <use-fast-fail>false</use-fast-fail>
</validation>

par

<validation>
    <check-valid-connection-sql>select 1</check-valid-connection-sql>
    <validate-on-match>true</validate-on-match>
</validation>

Pour JBoss AS 7.1.1 la première solution fonctionnait mais sous JBoss EAP 6.3 non … ce fut compliqué à le détecter et, malheureusement, ce fut via un incident en production. D’ailleurs c’est une soumission de bug qui m’a permis de comprendre le problème (içi).

  • Le mot de passe pour l’accès à distance (dans les fichiers application-users.properties et mgmt-users.properties) n’était plus utilisable car trop simple alors qu’il devait avoir au moins un chiffre. Corrigé en reployant l’application distante avec un nouveau mot de passe.

De plus cette migration a été l’occasion de faire évoluer la version du framework Spring ainsi que d’autres composants additionnels non présent dans JBoss EAP 6.3 et donc forcement il y a avait encore plus de points à régler.

Au final cela a demandé environ un mois de travail pour un déploiement sur 14 serveurs (sans compter les postes développeur, évidemment).

Dans le même temps je suis en train d’étudier une migration vers WildFly 8.1 mais certaines fonctionnalités sont totalement différentes comme par exemple JBoss Web (basé sur Catalina aka le moteur de Tomcat) qui a été remplacé par Undertow ou encore RestEasy qui passe de la branche 2.x vers la branche 3.x. Cependant le déploiement sur 14 serveurs m’a refroidi car cela demande presque 1/2 journée pour préparer chaque serveur alors qu’avec Docker/Chef/Puppet etc ce sera beaucoup plus rapide …