Java / Javascript / PHP / etc.

Au vu du nombre de langages disponibles dans le secteur des nouvelles technologies il devient de plus en plus difficile de choisir de s’investir sur un langage ou un autre. Je pratique le Java depuis maintenant 12 ans et il faut dire que ces dernières années l’informatique a changé à un point que je n’aurais pu imaginé 12 ans auparavant.

Le moteur de ces changements c’est le tout connecté donc Internet et les périphériques mobiles. Ainsi pour une entreprise moderne suivre ce mouvement impose d’avoir un système d’information (ou du moins une partie) pouvant suivre ces évolutions.

En clair pour créer un nouveau produit / une nouvelle prestation quelle technologie utiliser en 2014 ? Supposons qu’il faille partir de zéro, quoi choisir ? Il y a 12 ans s’il s’agit d’un site Internet cela aurait été du PHP avec du MySQL et un frontal Apache (souvenirs souvenirs). Dans un contexte d’entreprise avec plusieurs développeurs le Java était aussi un très bon choix, moins facile à aborder mais plus puissant.

Maintenant … je n’arriverais pas à choisir. Il s’agit parfois plus d’une question de philosophie et/ou de compétences que de pertinence. PHP ? OK mais par exemple avec le framework Symfony. Et encore je me porterais plutôt sur d’autres choix : soit Javascript (avec Node.JS) soit Java (avec Spring Boot). Le premier sera idéal pour démarrer ou avec des contraintes de charges mais le deuxième sera plus judicieux dans un contexte d’entreprise (attention c’est un choix strictement personnel, il existe tellement de langages / plateformes …).

L’évolution de l’informatique (et de ses services) s’accélère et c’est bigrement motivant. Mais aussi frustrant car il est plus en plus difficile de faire les bons choix.

Au final dois-je laisser tomber Java au profit de Javascript ? Non ! Mais apprendre les deux et concilier deux mondes différent oui !

Tester Keycloak sur Amazon EC2

En voulant tester WildFly via Docker sur Amazon EC2 je suis tombé par hasard sur le projet Keycloak. Ce projet consiste à pouvoir gérer du SSO/une IDM entre différentes apps et/ou API REST. A la base il se déploie sur WildFly mais peut finalement être mis sur d’autres serveurs. Je vous laisse découvrir le projet via le screencast de 15 min.

Mais en fait le mieux de l’installer et le tester. Pour cela j’ai utilisé Amazon EC2 en étant dans la période de gratuité de 1 an de celui-ci mais en étant donc limité à des instances de type t2.micro (sur le lieu « US West (Oregon) ») mais qui suffisent pour des tests.

Voici le déroulé pour l’installation de Keycloak sur Amazon EC2 :

  • Connectez-vous sur la console d’administration d’Amazon Web Services et sélectionnez le service « EC2 ».
  • Cliquez sur « Launch Instance » et sélectionnez une image de type « Ubuntu Server 14.04 LTS ».
  • Sélectionnez votre type d’instance. Dans mon cas et pour rester dans le cadre de l’utilisation gratuite d’Amazon Web Services j’utilise une instance de type « t2.micro ». Cliquez ensuite sur « Next: Configure Instance Details ».
  • Pour ma part à ce stade je clique sur « Review and launch » mais vous pouvez à la place configurer d’autres paramètres comme notamment l’intégration de la machine à réseau déjà existant. Mais ce n’est pas là l’objectif de l’article.
  • L’écran affiche un résumé des propriétés de la nouvelle instance. Par défaut il y a un accès SSH all over the world (en supposant que vous ayez déjà configuré une clé SSH pour Amazon Web Service, voir içi). Attention, à ce stade il faut modifier les règles d’accès à l’instance en changeant « SSH » par « All TCP » pour que n’importe quel port soit accessible depuis Internet. Pour cela dans la partie « Security Groups » cliquez sur « Edit security groups » et changez « SSH » en « All TCP » puis cliquez de nouveau sur « Review and launch ». Vous pouvez enfin cliquer sur « Launch » et sélectionner une clé SSH pour y accéder en SSH.

Une fois ceci effectué votre instance est en cours d’initialisation. Cliquez sur « View Instances » et attendez 2 minutes …

Quand votre nouvelle instance est notifiée comme « Running » et non « Initializing » c’est que vous pouvez désormais y accéder via SSH en utilisant l’adresse réseau affichée dans la colonne « Public DNS ». Donc allons-y avec la commande ssh (avec l’adresse réseau fournie par Amazon EC2) :

> ssh -i ec2.pem ubuntu@ec2-54-148-255-72.us-west-2.compute.amazonaws.com
[…]
ubuntu@ip-172-31-38-59:~$

Maintenant que vous êtes connecté à votre instance EC2 vous pouvez installer docker mais aussi l’image Keycloak :

sudo apt-get install docker.io
[…] (une dizaine de secondes)
sudo docker pull jboss/keycloak
[…] (1 Go à télécharger en moins de 2 minutes)

A ce stade Docker est installé et l’image de Keycloak est prête (enfin presque). Pour la démarrer :

sudo docker run -it -p 80:8080 -p 9090:9090 jboss/keycloak

Si ensuite, dans votre navigateur préféré vous tapez l’URL (en fonction du DNS fourni par Amazon EC2) :

http://ec2-54-148-255-72.us-west-2.compute.amazonaws.com/auth/

Vous devriez alors avoir la page suivante :

keycloak_welcome

Maintenant pour accéder à la console d’administration de keycloak ce n’est pas possible de base car il faut que ce soit effectué via SSL/HTTPS. J’ai bien essayé de configurer Keycloak pour lui indiquer de passer malgré la non présence de SSL (utile avec proxy reverse comme Nginx ou Apache gérant lui même le SSL) en modifiant le fichier /opt/jboss/wildfly/standalone/deployments/auth-server.war/WEB-INF/classes/META-INF/keycloak-server.json via la commande (dans le conteneur jboss/keycloak) :

sed -i 's|    "admin|    "ssl-required": false,\n    "admin|' /opt/jboss/wildfly/standalone/deployments/auth-server.war/WEB-INF/classes/META-INF/keycloak-server.json

Mais cela ne semble pas marcher alors que le fichier est bien modifé Bon solution de secours j’utilises SSH avec une redirection de port :

ssh -i ec2.pem -L 3000:127.0.0.1:80 ubuntu@ec2-54-148-255-72.us-west-2.compute.amazonaws.com

En tapant dans un navigateur l’adresse http://127.0.0.1:300/auth/admin/ cela fonctionne enfin ! J’utilise le login et mot de passe admin/admin, Keycloak me demande de modifier ce mot de passe suite à une première connexion. Après cela j’ai enfin accès à la console de Keycloak.

Voilà maintenant vous pouvez jouer avec cette console afin de voir ce qu’elle propose comme fonctionnalités.

Run Above & So You Start

Mon cher responsable administrateur réseaux de ma société, en discutant Cloud avec lui, m’a parlé de So You Start d’OVH . Étant en grande observation des acteurs du Cloud et notamment Amazon EC 2 j’ai consulté l’offre de So You Start et j’avoue avoir été, de prime abord, très tenté de l’acheter à titre personnel : moins de 40€ par mois pour un serveur physique dédié décent pouvant faire tourner un ESXi pouvant lui-même faire tourner, avec la configuration de So You Start, près de 10 machines virtuelles fonctionnelles (dans un objectif d’architecture de SI orientée web).

Alors pourquoi ne pas l’avoir acheté ? Parce que je n’avais pas ma carte bleue sur moi ! Et puis mon administrateur réseaux m’a dit qu’on avait un abonnement So You Start que je pouvais tester de moi même en me donnant les accès complet sur le VM Ware ESXi réinstallé fraichement à ma demande. Alors autant le tester à fond avant d’y aller !

Alors de prime abord c’est la panade pour un développeur hybride dev/op surtout après avoir testé Amazon EC2. OVH c’est une société française (bon peu importe ?) : j’ai déjà un hébergement mutualisé depuis 2005 (déjà ??) mais OVH arrive quand même à être à la hauteur, en terme de tarif, d’Amazon EC2 quand il s’agit de plusieurs VMs. J’ai déjà l’habitude de créer des infrastructures web de type frontal Nginx avec ensuite des serveurs web (au moins 2) de type JBoss  / WildFly et un serveur applicatif Java EE toujours sous JBoss / WildFly avec enfin un serveur de fichier. N’oublions pas la base de données … Cela fait donc 6 serveurs. Actuellement ma société paye plus de 1500€/mois pour l’équivalent de cette infrastructure MAIS il s’agit d’une prestation que l’on peut qualifier de haut de gamme : l’hébergeur s’occupe de presque tout.

Et donc à coté So You Start permet de faire l’équivalent en moins de 40€/mois … J’ai donc testé en essayant de faire un frontal de type Nginx sous VM Ware ESXi … j’ai eu peu galéré pour que ce frontal puisse avoir accès à Internet via une IP dédiée. Après j’ai créé un serveur web de type Tomcat. Et là tout est OK en moins 2 jours j’ai eu mon frontal et un serveur web prêt à accepter un livrable Java (un WAR). Mais pas encore de BDD. Le problème à ce stade c’est comment que le serveur web (pas le frontal) ait accès à Internet ? Aie aie voilà où commencent les problèmes alors l’admin réseaux me dit « pas de problèmes rajoute un firewall de type PfSense ! ». PfSense … intéressant (très même). Il s’agit d’un Firewall basé sur un FreeBSD agissant en tant que machine virtuelle et permettant, grace à ESXi de distribuer Internet à toutes les autres machines virtuelles gérées dans ESXi. Ok … j’ai essayé d’installer PfSense via une ISO et … OVH possède une IP de passerelle en dehors du masque de l’IP de failover fournie pour joindre le firewall depuis Internet et PfSense ne l’accepte pas dans sa configuration standard demandant une manipulation spécifique (voir içi).

Vous êtes perdu ? Moi aussi à ce stade. En discutant avec l’admin réseaux j’ai compris le pourquoi du comment mais surtout j’ai compris qu’avec So You Start, et pour un dev/op modeste il faut avoir un admin réseaux pour gérer le réseaux entre tous les VMs (je n’ai pas testé le Firewall fourni par OVH à raison de 28,8€ par mois, en tant que particulier cela explose le tarif mensuel).

Et pour en remettre une couche l’admin réseaux m’a expliqué ce qu’il se passait quand on dépassait la capacité du VM Ware ESXi fourni : il faut prendre une nouvelle machine chez So You Start gérée avec VM Ware ESXi mais avoir des règles de Firewall encore plus compliquées. Dans ce cas l’admin réseaux est votre bouée de secours. Bref avec le Cloud ne dites pas à votre admin réseaux qu’il ne sert plus à rien vous risquez de le regretter.

Mais … mais … OVH fourni un autre service appelé Run Above qui offre une tarification totalement différente. En fait cela est vraiement l’équivalent d’Amazon EC2 (désolé pour moi c’est la référence). Il s’agit donc de pouvoir créer UNE machine virtuelle à la demande. Pour un simple serveur web créé en un rien de temps (et joigneable via SSH) une tarification mensuelle de 7€ (9$) est appliquée. A vrai dire la tarification est par heure et ça c’est super pour un dev/op (enfin plus un dev) : tester le déploiement en quelques heures ne coûtera que 0,13€ (1/2 journée de travail). Et bonus pour ce prix là on peut avoir un serveur Windows Server 2012 (pas de gestion de licence).

Ok super et quid d’une architecture SI avec Run Above ? Hum en fait en prenant les 6 serveurs avec So You Start cela revient finalement à 7€ x 6 soit 42€ par mois. C’est déjà plus que So You Start de base (36€ / mois). Mais attention Run Above gère une sorte de Firewall qui est à 28€/mois avec So You Start …

Bref le Cloud c’est parfois aussi une histoire de facturation mais aussi … d’admin réseaux ! Si vous avez un admin réseaux compétent dans les VMs et notamment VM Ware ESXi alors So You Start est très bon marché. Par contre pour un développeur Run Above est bien plus abordable (la SandBox à une poignée d’euros !) MAIS s’il s’agit de faire un SI complet au final cela risque d’allonger la facture.

Mais dans tous les cas Amazon EC2 ou OVH (via So You Start ou Run Above) est beaucoup plus abordable que des hébergeurs dédiés. Cependant attention … pas de monitoring, pas de support direct.

Bref à chacun son choix !

JHipster

Hier j’ai parlé de Spring Boot qui fait parti des projets Hype du moment pour tout développeur Java. En fait la problématique c’est comment démarrer rapidement un projet web (ou autre) ? Spring Boot répond à ce besoin de pouvoir faire un site web ou une API Rest (ou encore une fois autre) en quelques lignes de code.

Cependant en parallèle Node.JS est devenu très populaire car le Javascript est devenu très populaire (Node.JS c’est du Javascript coté serveur ET en asynchrone : bonus XXL).

Mais voilà Spring Boot est un bon départ mais après il reste à faire une interface avec Angular JS (ça aussi c’est Hype, enfin surtout pour un backoffice ou une application de gestion, mais en tout cas j’adore), mais aussi lier à une une base de données (MongoDB c’est Hype, MySQL/PostgreSQL c’est aussi pas mal pour structurer ses données), loguer, mesurer, déployer, etc …

La solution ? Le projet JHipster ! Il s’agit d’un projet géré via yeoman c’est à dire qu’il faut installer Node.JS (tiens encore lui) et d’installer yeoman via npm, le gestionnaire de package de Node.JS pour enfin avoir la commande yo afin de faire un petit yo jhipster et de répondre à toute ses questions (choisir sa base de données, son gestionnaire de package, la manière d’identifier un utilisateur, etc.). JHipster consiste à la fois à du code Java (une API Rest + des templates délivrés à Angular JS) mais aussi à une interface de type SPA avec Angular JS, BootStrap, etc avec l’utilisation, en bonus de très bonnes librairies comme Metrics ou Swagger.

Jusqu’à maintenant je connaissais les archétypes maven, notamment le kickstart de Spring 4 MVC ou encore les quickstarts de JBoss ou encore JBoss Forge mais aucun ne faisait du fullstack en alliant le monde Java (via Spring) et le monde Javascript (via Grunt/Bower/etc.). C’est donc chose faite via JHipster et en plus via une SSII français aka Ippon Technologies (société auquelle j’avais postulé en 2008, je regrette parfois de ne pas avoir accepté la proposition finale). Le site web lié explique très bien comment cela fonctionne, comment l’installer, comment le déployer, etc. Bref, bravo. Après certaines choses ne me conviennent pas (je suis très difficile) à savoir que je préfère utiliser un serveur Java EE plutôt que tomcat et donc d’utiliser des DataSource(s) (tomcat peut le faire) l’utilisation de JTA/JPA et si possible de JAX-RS (via Jersey ou RestEasy) voir plus si possible (qui peut le plus peut le moins).

Donc JHipster est une très bonne base pour un projet Hype, mais, comme toujours, demande de l’ingénierie pour l’adapter à son propre contexte.

Note à part : JHipster fonctionne sous WildFly 8.1 il suffit juste de ne pas intégrer les librairies tomcat-*.jar dans le WAR généré. Par contre je ne suis pas arrivé à intégrer Spring Boot en tant que module dans WildFly. Donc le WAR fait plus de 50Mo et n’est pas allégeable avec WildFly. Si le serveur d’intégration continue est en entreprise mais que le déploiement est dans un cloud privé alors cela est problématique de transférer 50 Mo à chaque déploiement … A travailler.

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.

Node.JS

Il y a maintenant deux mois que j’ai découvert Node.JS. Pour comprendre la bête j’ai migré une de mes applications personnelle de PHP vers Node.JS d’autant que cette dernière souffrait d’un manque de vitesse notoire.

Pour un développeur Java (et PHP) ne connaissant pas totalement le Javascript (sauf à travers de JQuery & co) ce fut assez épique mais au final cela en valait la peine. J’ai effectivement pu constater un gain de performances énorme.

Mais voilà … au delà d’avoir appris à faire du Javascript comme un ninja je me suis confronté à la barrière de la programmation « réactive » à savoir mono-thread mais basé sur des callback. Bref de la programme non-bloquante, asynchrone.

Cela fait plus de 25 ans (j’ai commencé tôt) que je développe de manière procédurale et synchrone ou, au mieux, en utilisant des Thread dans Java. Alors la programmation asynchrone …

En fait le plus déroutant c’est :

function readFile(callback) {
	fs.readFile('/etc/passwd', function (err, data) {
		callback(err, data);
		return data;
	});
	return 'Euh ?';
});

(code affreux, c’est pour l’exemple)

Dans l’exemple la fonction fera deux return ? C’est le premier qui gagne ? Et les données du fichier elles envoyées où ?

Je pense trop au callback comme un fork alors que, justement cela n’a rien à voir. Donc il va falloir que je trouve un article expliquant le mécanisme de programmation asynchrone coté machine.

En tout cas je n’ai aucun doute que ce style de programmation va devenir la norme coté Web car sinon impossible de pouvoir traiter des milliers (et bien plus) d’appels simultanés.

A ce sujet j’ai trouvé un tas de choses intéressantes du coté du blog d’Octo Technologie pour le tag reactive. Et d’ailleurs, en tant que développeur Java, j’ai notamment bien aimé l’article « Java 8 est réactif !« .

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 …

Design pattern : Double-checked locking

Un article intéressant sur Wikipedia concernant le design (anti) pattern « Double-checked locking »

Double-checked locking

C’est subtile, pas toujours évident au premier coup d’oeil mais finalement on comprend qu’il s’agit d’un risque elevé d’erreurs … bien après avoir exploité le pattern.
Et puis c’est toujours bon de se rafraîchir la mémoire concernant le mot clé « volatile » introduit par Java 5.

Hibernate (4) vers JPA

Dans le cadre d’une migration d’un applicatif tournant sous JBoss AS 7 il est désormais voulu passer de l’objet SessionFactory vers son pendant en JPA : EntityManagerFactory.

Via JNDI JBoss expose l’objet EntityManagerFactory avec la propriété suivante dans le fichier persistence.xml :

<property name="jboss.entity.manager.factory.jndi.name" value="java:/jboss/MyEntityManagerFactory" />

Le problème c’est qu’actuellement tout le code de notre application exploite un SessionFactory et il n’est pas question de repasser partout où un SessionFactory est exploité pour le remplacer par un EntityManagerFactory.

En regardant, en mode debug, quelle est la classe implémentant EntityManagerFactory sous Hibernate on trouve qu’il s’agit de la classe org.hibernate.ejb.EntityManagerFactoryImpl. En regardant son code source via grepcode (içi) et pour la version 4.0.1 d’Hibernate (celle exploitée par JBoss AS 7.1.1.Final) on s’aperçoit qu’un objet SessionFactory est directement embarqué dans l’implémentation.

Au final il suffit donc d’utiliser ce code :

SessionFactory sessionFactory = ((EntityManagerFactoryImpl) entityManagerFactory)
    .getSessionFactory();

Note : cette classe se trouve dans le JAR jboss-as-7.1.1.Final/modules/org/hibernate/main/hibernate-entitymanager-4.0.1.Final.jar

A noter qu’il y a une deuxième possibilité : préciser à Hibernate d’exposer l’objet SessionFactory via JNDI. Cela s’effectue via une propriété dans le fichier persistence.xml :


<property name="hibernate.session_factory_name" value="java:/hibernate/HibernateVPCFactory" />

Cette solution n’a cependant pas été retenue pour forcer l’exploitation d’un objet EntityManagerFactory. Mais après rien n’empêche le développeur de récupérer un SessionFactory cependant la méthode permettant de le faire a été marquée @Deprecated pour lui indiquer d’utiliser EntityManagerFactory.

JBoss AS 7 : org.omg.CORBA (SUN)

JBoss AS 7 est fourni avec un module nommé JacORB qui est une librairie standard repackagée par JBoss afin d’exploiter les services CORBA. Ce module possède sa propre implémentation du client CORBA mais rédéfini aussi les interfaces de cette implémentation à savoir le package org.omg.CORBA.* présent au sein de la JRE.

Le problème se pose quand (comme dans mon cas) il faut pouvoir exploiter l’implémentation CORBA d’origine de la part de SUN, par incompabilité par exemple. Normalement il faut, pour cela, définir une propriété système ayant pour clé « org.omg.CORBA.ORBClass » et pour valeur la classe implémentant CORBA (et qui doit étendre la classe org.omg.CORBA.ORB).

A priori, avec JBoss AS 7, tant que le module JacORB n’est pas défini comme dépendance par une application (par exemple via un fichier jboss-deployment-structure.xml) les classes de ce module ne sont pas chargée (pour l’application). Cela est vrai pour les classes org.jacorb.* MAIS cela n’est pas vrai pour les classes org.omg.CORBA.* qui sont quand même chargée pour l’application et cela même en excluant explicitement le module org.jacorb.

Ainsi en effectuant le code suivant :

org.omg.CORBA.ORB.init(null, null)

La classe ORB possède un classLoader de type « ModuleClassLoader » issu … du module JacORB. OK … Je n’ai pas réussi à faire en sorte que la classe ORB soit bien celle du Sun (par exemple en excluant le mode « org.omg.api » au sein de mon application). La seule solution qui s’avère fonctionner (parmi tout ce que j’ai essayé) c’est de changer le classloader utilisé dans un nouveau thread : ce nouveau Thread va instancier la classe ORB (avec la bonne instanciation) rendant ensuite disponible la bonne classe aux autres Thread (?).

Voici le bout de code :

public class MyBusiness {
    private static boolean jboss7Init = false;

    /*
     * Initialisation du système PCRE pour JBoss AS 7
     */
    private static void initPCREforJBossAS7(final String serverName) throws Exception {
        final Exception[] threadException = new Exception[1];

        logger.info("Initialisation du système PCRE (CORBA) pour JBoss AS 7 (Serveur : "
            + serverName + ")");

        Thread t = new Thread() {
            public void run() {
                try {

                    ClassLoader cL = this.getContextClassLoader();
                    String cLName = cL.getClass().getName();

                    try {
                        if (cLName.equals("org.jboss.modules.ModuleClassLoader")) {
                            // C'est un class loader de JBoss AS 7 qui peut, pour la classe
                            // omg.org.CORBA.ORB, l'instancier vis à vis de son propre module
                            // org.jacorb. Pour éviter cela on utilise un classLoader supérieur
                            // à celui du module
                            Thread.currentThread().setContextClassLoader(cL.getParent());
                        }

                        PCREApplicationClient client = new PCREApplicationClient("SILVERPROD02");

                        client.Connect();

                        logger.info("Connecté au serveur PCRE (" + serverName +
                            ") : version = " + client.getServer().GetVersion());

                        client.Disconnect();

                    }
                    finally {
                        Thread.currentThread().setContextClassLoader(cL);
                    }
                } catch (Exception e) {
                    threadException[0] = e;
                }
            }
        };

        t.start();
        t.join();

        if (threadException[0] != null)
            throw threadException[0];
    }

    private void openClient() throws PCREClientError {
        if (this.getClass().getClassLoader().getClass().getName().equals(
            "org.jboss.modules.ModuleClassLoader")) {
            if (!jboss7Init) {
                jboss7Init = true;
                try {
                    initPCREforJBossAS7(serverName);
                } catch (Exception e) {
                    e.printStackTrace();

                    throw new PCREClientError(e.getMessage());
                }
            }
        }

        client = new PCREApplicationClient(serverName);
    }

    public void doBusiness() {
        openClient();

        ...
    }
}

Evidemment ce code est absolument affreux mais est, pour l’instant, une solution de secours pour avoir au moins UNE solution qui fonctionne.

A noter que dans le cas ci-dessus il s’agit d’une librairie « PCRE » qui est utilisé pour se connecter à un serveur Parallel Crystal (aka Crystal Report 7). La librairie « PCRE » effectue un ORB.init(null, null) et est configurée en tant que module :

 <?xml version="1.0" encoding="UTF-8"?>


<module xmlns="urn:jboss:module:1.1" name="com.dynalivery.pcre">
    <properties>
        <property name="jboss.api" value="private"/>
    </properties>

    <resources>
        <resource-root path="PCREJavaClient.jar"/>
        <resource-root path="PCREJavaClient_SunStubs.jar" />
    </resources>

    <dependencies>
        <system>
            <paths>
                <path name="com/sun/corba/se/impl/orb" />
                <path name="org/omg/CORBA" />
                <path name="org/omg/CORBA/ContainedPackage" />
                <path name="org/omg/CORBA/ContainerPackage" />
                <path name="org/omg/CORBA/InterfaceDefPackage" />
                <path name="org/omg/CORBA/ORBPackage" />
                <path name="org/omg/CORBA/portable" />
                <path name="org/omg/CORBA/TypeCodePackage" />
                <path name="org/omg/CORBA/ValueDefPackage" />
                <path name="org/omg/CORBA/ValueDefPackage" />
                <path name="org/omg/CORBA_2_3" />
                <path name="org/omg/CORBA_2_3/portable" />
                <path name="javax/rmi/CORBA" />
            </paths>
        </system>
    </dependencies>
</module>