Vavr, tu vas voir !

Merci à Norsys, qui offre le food truck ce soir (!). (par contre, le chauffage semble être mort dans la soirée).

Guillaume nous vient de chez Saagie (où je connais quelqu’un …​ depuis pas mal de temps) dans l’équipe d’outillage. Et quand il parle, j’ai presque l’impression d’entendre parler un collègue tout aussi barbu, mais plus rancheros …​

La programmation fonctionnelle

C’est de la programmation sans effet de bords, et c’est cool. Et pour faciliter ça, les fonctions sont des éléments essentiels du langage, les variables sont immutables (ça n’a pas de rapport avec la programmation fonctionnelle, en vrai, mais ça fait maintenant partie du canon fonctionnel).

Enfin, ce qui est important pour Guillaume, c’est aussi la transparence référentielle (ou referential transparency) qui garantit que deux appels à la même fonction retourneront le même résultat.

Par exemple, Math.random() ne respecte pas cet aspect, mais Math.max(1, 2) oui.

Java 8 est déja fonctionnel ?

Ben oui, avec les lambda, les streams, les Optional<?>, c’est un début. Mais pour Guillaume il manque des trucs.

Vavr …​ anciennement Javaslang

La librairie a été créée par un développeur Scala frustré par Java. Et le nouveau logo retourne joliment Java …​

Les collections Java, c’est pas pratique

Il y en a en java …​ mais c’est loin d’être pratique. Parce qu’à la base les collections sont conçues pour être mutables (et pas parce qu’ils n’ont pas compris l’immutabilité). Autrement dit, elles ne sont pas joliment immuables, ce qui fâche les puristes. Donc vavr redéfinit ses collections (y compris un Vector).

Typiquement, les méthodes Collection.stream() et Stream.collect() n’existent pas en vavr, parce que les collections sont conçues autour de concepts fonctionnels.

Guillaume mentionne ensuite un point intéressant : en programmation fonctionnelle, on n’aime pas trop les exceptions parce qu’elles ne respectent pas trop le flux d’opérations.

Streams inconsistents

Parfois, les streams Java démarrent leurs opérations un peu en avance. Du coup, deux appels successifs à Stream.map`(…​.)` peuvent balancer des exceptions, ce qui est insupportable pour Guillaume …​ Peut-être pas autant pour moi.

Streams de Map

En Java, utiliser un stream sur une map, c’est l’enfer (il faut faire le stream sur l’ entrySet() et reconstruire la Map au moment du collect). Par contre, en vavr, c’est super facile parce que vavr va mapper les couples clé/valeur vers des Tuple.

Value types

Ils arriveront en Java 10, peut-être (il faudrait demander à Rémi Forax). En revanche, il y en a un paquet dans vavr, inspirés de Scala, évidement.

Option

Hey, mais l’ Option de vavr est sérialisable ! C’est très cool !

Try

Qui permet d’encapsuler du code susceptible de lancer une exception. L’exception sera gentiment catchée et conservée. C’est pas bête du tout.

Either

Là, on est en plein dans la scalaterie. Ca permet de retourner deux types différents en disant que le retour est soit l’un soit l’autre. Bon, jusque là, c’ets un tuple. La particularité d’ Either, c’est qu’on prend comme convention que le bon cas est celui de droite …​ autrement dit le deuxième …​ Je trouve ça pénible et un authentique retour en arrière.

Validation

Qui ressemble furieusement à Bean Validation dans l’objectif …​ mais pas du tout dans l’implémentation, puisque c’est encore un Tuple, voire même un Either particulier.

Des fonctions

vavr ajoute aux Function et BiFunction des interfaces permettant d’utiliser jusqu’à 8 paramètres. Ca n’est pas très pur fonctionnellement, mais c’est bien pratique.

Composition

Mais bien sûr qu’on peut composer des fonctions avec vavr !

Lifting

Chez les fonctionnalistes, c’est la transformation d’une fonction impure en fonction pure. Et je dois bien dire que c’est assez propre.

Application partielle de fonctions

Là aussi, ça fait rêver tous les haskelliens, et c’est assez simplement réalisé. Mais mon voisin pose une excellente question : si j’applique ma fonction partielle à 5 paramètres, lequel reste à utiliser ? Le premier ou le dernier ?

Curryfication

A priori, c’est très semblable à l’application partielle, tout en étant subtilement différent.

Mémoisation

Un peu comme un cache, en fait …​ mais sans avoir besoin de réécrire à chaque fois.

Et maintenant, le pattern matching

Alors là ça va être un peu fou …​ Toujours est-il que, vous le savez maintenant, le pattern matching, c’est un switch sous stéroïdes (mais alors beaucoup de stéroïdes). Par contre, comme vavr reste du Java, c’est la syntaxe habituelle qui est utilisée. Et du coup, c’est moins surprenant puisque l’instruction langage est remplacée par des appels de méthode dans tous les sens. Ca n’est pas forcément très lisible à mon sens, mais bon. En revanche, ce qui est vraiment moche, c’est que le cas d’usage typique, c’est pour faire des instanceOf plus propres de la manière suivante :

Number plusOne = Match(obj).of(
    Case($(instanceOf(Integer.class)), i -> i + 1),
    Case($(instanceOf(Double.class)), d -> d + 1),
    Case($(), o -> { throw new NumberFormatException(); })
);

Bon, ben là, franchement, je suis désolé, mais il n’y a aucune espèce de gain par rapport au simple instanceofdans un if (qui est un foutu antipattern).

Par contre, pour filtrer une liste d’adresses entre valides et invalides, c’est pas mal du tout (merci Either).

Property Checking

On parle ici de la génération automatique de cas de tests. Et il y a pour les différents types de variables simples, des générateurs aléatoires inclus. Ca n’est pas inintéressant …​ mais le test est salement pollué par tout le code supplémentaire nécessaire pour gérer ce contenu aléatoire. Il me semble qu’il y a d’autres outils qui fournissent le même genre de services

Conclusion

La présentation était intéressante et Guillaume sacrément motivé pour nous convaincre (et ça, c’est très cool). Néanmoins, je ne peux pas m’ôter de la tête l’idée que vavr est avant tout un exercice de style, une espèce de figure imposée éventuellement utilisable sur un projet, mais dont ça n’est pas le but premier. Pour moi, le but de ce genre de librairie (comme ça a pu l’être quand j’ai écrit gaedo), c’est avant tout de tester la faisabilité d’un concept. Après, pour l’utiliser, il faut quand même avoir des besoins qui sont à mon sens particulier (surtout si quelqu’un veut sortir de Java 8 pour utiliser vavr). L’idée est néanmoins intéressante, et certains aspects m’ont paru particulièrement séduisants.

Publicités

Keycloak au chtijug

 

 

Thibaut commence par nous présenter KaliCustomer …​ le nouveau nom d’Onyme. Qui fait donc du suivi de la satisfaction client à travers des questionnaires envoyés. Un truc amusant, c’est qu’Onyme est devenu un éditeur de logiciel en 2010, après avoir été longtemps une ESN.

Revenons donc à Keycloak …​

Ca envoie du rêve !

Et commençons donc par une démo. Une démo assez simple, puisque nos speakers vont coder une application Spring Boot …​ depuis start.spring.io (qui fournit un chouette générateur de pom). Donc, après un peu de code, le contrôleur est implémenté avec une vue thymeleaf. Il y a deux ou trois trucs que je trouve un peu moche avec Spring Boot, mais bon …​ pour l’instant ça marche.

On installe ensuite Keycloak, qui est en fait l’outil de sécurité de JBoss Wildfly, et packagé également pour servir des applications externes (heureusement). Du coup, paf, on crée un realm, hop, un utilisateur, boum, on connecte l’application côté Keycloak.

Et ensuite, il faut configurer l’application elle-même. Ce qui est un tout petit peu fastidieux (du moins quand on le présente en conférence). Par contre, d’une façon un peu dommage, la demande d’authentification sur un contrôleur n’est pas dans le contrôleur (sur une annotation, typiquement), mais dans une configuration séparée.

Après un peu de configuration complémentaire, Keycloak intercepte bien les requêtes pour accéder aux pages demandant une authentification.

Du coup, la suite logique, c’est d’avoir un service externe qui fournit une liste de bières à un autre service qui affiche ces bières, les deux utilisant une identité qui est propagée par keycloak.

Et bon, là, on intègre Keycloak dans du nodejs, et c’est à peu près pareil …​ mais plus sale.

Et surtout, ça marche.

Et on passe maintenant au client, en HTML+Javascript (mais sans framework infame). Et pour ça, Keycloak fournit un connecteur Javascript pour les clients directement depuis le serveur, ce qui est assez cool. Et qui permet de garantir que le client utilise la bonne version de l’API de sécurité. Et ça marche …​ simplement (pour du Javascript).

Plus sérieusement

Keycloak est un produit sérieux, avec des connecteurs pour toutes les bases de données, LDAP, Kerberos, …​ Par ailleurs, il supporte OpenID, OpenID Connect, OAuth, et SAML (mais on ne parle pas de SAML). Thomas enchaîne ensuite par une présentation de ces protocoles, que je ne vais pas vous relater ici (parce qu’il y a quand même tout un paquet de sites de qualité sur le sujet). Par contre, je ne connaissais pas JSON Web Keys

Et sous le capot de Keycloak ?

Donc l’interface de saisie est facilement configurable (via des thèmes) et on peut aussi changer la langue de l’interface simplement en activant l’internationalisation. Comme Keycloak est un service d’identité, il est évidement possible de permettre aux utilisateurs de s’enregistrer eux-même (le scénario typique dans un site grand public). Et évidement, la page de création d’utilisateur est fournie par Keycloak …​ Il est évidement possible d’envoyer des mails pour les mots de passe oubliés ou pour vérifier les emails des utilisateurs, mais ça implique d’avoir configuré un serveur SMTP (comme par exemple Fake SMTP Server – bon en fait il y en a plusieurs : en Java (http://nilhcem.com/FakeSMTP/), en .Net (https://fakesmtp.codeplex.com/), très pratique pour le développement). En bonus, lorsque l’utilisateur clique sur le lien de vérification d’email, il est authentifié et connecté à l’application, ce qui fournit une meilleure expérience utilisateur. A part les utilisateurs simples, Keycloak peut aussi utiliser les logins sociaux (GitHub, Google, StackOverflow, …​). Et si votre site préféré n’est pas présent, il est possible de créer une extension Keycloak …​ ou encore d’utiliser les protocoles standard (OAuth, OpenID).

Pour revenir aux cas simples, Keycloak fournit évidement des outils de gestion de qualité de mot de passe. Mais aussi, et surtout, Keycloak met à jour régulièrement sa politique de hashage des mots de passe, et lorsque cette politique change et qu’un utilisateur se logge avec un mot de passe hashé avec un vieil algorithme, il re-hashe le mot de passe avec le nouvel algorithme. Très cool. Un autre truc vraiment très cool, c’est de pouvoir prendre l’identité d’un utilisateur (pour peu qu’on dispose des privilèges suffisants). Et ça, pour les développeurs, c’est quand même super chouette. Et si vous voulez vous compliquer la vie, l’authentification deux facteurs est supportée via FreeOTP ou Google Authenticator.

Conclusion

Certains éléments des démos ont été particulièrement bluffants. Et je l’utiliserai bien …​ si j’avais à développer une solution de gestion de l’identité. Mais ça n’est pas vraiment le genre de projet qui se fait toutes les cinq minutes …​ Sauf dans les petites boîtes.

Scala, c’est l’histoire d’un type

Hier soir, c’était … chtijug !

Et comme je me suis occupé d’aller chercher toutes les bières (et de les servir), je n’ai pas suivi très attentivement la présentation de Valentin Kasas. Pas de panique, j’ai un collègue qui a produit un article de qualité.

Heureusement, elle est là

Et en la lisant, je ne peux m’empêcher d’avoir … certaines opinions.

Et comme je suis généreux, je vais vous les partager, parce que comme le dit l’inspecteur Harry

(je peux pas m’en empêcher)

A travers les différents éléments présentés (pattern matching, destructuring, méthode apply, case class, implicites), on voit bien que les concepteurs du langage ont cherché à mettre en place dans la JVM un langage aux fondations théoriques solides. Mais je crois profondément que l’intérêt d’un langage n’est pas dans ses fondations théoriques. Sinon, ni Python, ni Ruby, ni Java n’auraient percé, et on ferait tous gentiment du LISP, de l’Ada ou du PROLOG. Or ça n’est pas le cas.

Parce que ces langages, théoriquement puissants, manquent d’ergonomie. Et en l’occurrence, le coeur de mon idée, c’est que l’ergonomie de Scala est clairement défaillante. Défaillante, parce qu’il y a des tonnes de choses qui me semblent implicites, et d’autres qui sont vraiment à la limite de l’overengineering. Sans compter tous ces moments douteux où on sent bien la volonté de faire de « l’avant-garde ».

Bref, Scala, ça n’est pas trop ma came. Heureusement, je crois qu’on aura une présentation de Kotlin bientôt, qui m’a nettement plus intéressé pour l’instant.

Le loup de Wall Street

Lundi soir, j’ai regardé le loup de Wall Street. Un film qui a une sacrément bonne réputation.

Et honnêtement, le spectacle est saisissant. Un peu comme dans Wall Street, le personnage de Jordan Belfort y est décrit comme une espèce d’escroc boursicoteur, qui mise sur la stupidité de ses clients pour se faire des tonnes de pognon. Mais là où Gordon Gekko est décrit comme une espèce de reptile parasite, cet escroc-ci essaye de construire des choses : une famille, une entreprise, une culture. Bref, il a des aspirations qui le rendent attirant aux yeux du spectateur, ce qu’amplifie une mise en scène et un ensemble de dispositifs dénotant la maestria de Scorcese.

Mais, il y a aussi la drogue omniprésente et les femmes nues, éventuellement représentées en position de trophées. Bon, la drogue fait partie d’un imaginaire du trader bien connu, je ne m’attarderais pas trop dessus.

Par contre, les femmes nues … Je n’en peux plus.

Dans un film de trois heures, je dirais qu’il y a facilement 1/4 d’heure, voire 1/2 heures montrant des femmes plus que déshabillées. Et, collision intéressante de calendrier, ça arrive au même moment que les terribles histoires d’Harvey Weinstein, et le plus terrible encore #dénoncetonporc de Twitter. Du coup, je ne vais vous dire que ce film est avant tout une galerie permettant à de vieux producteurs dégueulasses de faire leur marché de jeunes actrices … Mais la défense de DiCaprio (que vous trouverez à la fin de ce chapitre de l’article Wikipedia) ne tient simplement pas : Scorcese et DiCaprio sont clairement fascinés par le personnage, et son apparente chute est montrée juste pour servir de « cache-sexe » devant l’obscénité du personnage présenté. Et de la part d’hommes de pouvoir dans le milieu d’Hollywood depuis vingt ans, ça devient particulièrement répugnant.

J’ai même en fait assez honte d’avoir regardé ce film bien filmé, mais idéologiquement pourri jusqu’au coeur. Franchement, le même film, tourné du point de vue de l’agent du FBI, m’aurait sans doute bien plus séduit.

Ah, et au fait, si vous pensez que c’est une montée de féminisme, elle n’est pas si récente, puisque j’ai aussi arrêté de regarder Game Of Thrones après la première saison à cause des femmes nues jetées à l’écran par HBO pour distraire le spectateur. La seule chose qui vaudrait le coup, ce serait une parité dans cette exposition frontale de nus : voir autant d’hommes que de femmes, ça aurait du sens en 2017. Ne montrer que de femmes, c’est se contenter d’une vision rétrograde de la beauté physique, et considérer les femmes comme des objets de concupiscence plutôt que comme une partie du public, c’est idiot, primaire et dépassé.

Hellboy

J’ai revu hier soir Hellboy.

Bon, dit comme ça, ça n’est pas très impressionant.

Mais … J’ai également lu plusieurs fois les comics dont ce film est tiré (j’ai d’ailleurs acheté le premier tome suite à un premier visionage de ce film). Et si j’avais donné mon avis sur Goodreads suite à cette première lecture, je crois que le film mérite deux ou trois mots.

D’abord (et à mon avis ça compte pas mal) visuellement : comment recréer le style incroyable de Mignolia au cinéma ? C’est impossible. Donc le réalisateur n’essaye pas trop (sauf dans un plan nous montrant les neuf qui sont un). Et il a raison, puisque l’ambiance est visuellement très différente, mais pas inintéressante … Pas inintéressante, mais pas suffisante pour rendre le film inoubliable.

Ensuite, il y a le casting. Ron Perlman qui cabotine pour donner un Hellboy peut-être un peu caricatural n’est pas mauvais du tout dans le genre bougon, mais je crains qu’il manque d’une certaine forme de finesse au moment de faire le choix qui va détruire le monde … ou pas. C’est dommage, parce qu’il est correctement massif, mais ne présente peut-être pas la bonne … faille. Dans le reste du casting, l’agent Myers qui n’est pas dans les comics est un ajout sympathique, une espèce de témoin d’humanité au milieu de la folie du BRPD qui nous relie un peu à ces marginaux. Et puis Liz Sherman … est aussi brillante qu’il le faut. Quant aux méchants, je trouve Raspoutine toujours aussi difficilement perceptible (au sens où ses motivations apocalyptiques sont totallement incompréhensibles), mais l’acteur le rend aussi inhumainement méchant qu’il est nécessaire. Et sa comparse Ilsa Haupstein est également bien campée. Bref, tout ça tourne bien … sauf pour la faute d’intelligence qu’est le chef du BRPD : lâche politicard quand Hellboy est une quête philosophique, il ramène des préoccupations bien trop prosaïques pour être utiles.

Parce qu’en vrai, le secret de cette oeuvre aussi bien au cinéma qu’en comics, c’est que c’est une oeuvre sur la réalisation de soi, quand bien même ça va à l’encontre de ce que veut l’univers. Le courage, c’est parfois refuser. Et ça, quel que soit le média, c’est le coeur de cette oeuvre, et il est bien passé hier soir.

Quand un non-événement devient un petit événement

Mercredi, l’un des disques durs de mon NAS a rendu l’âme (eh oui, encore). J’ai donc commandé un autre disque en ligne, et monté le nouveau disque dans le NAS. Après un poil de bidouille, le NAS a redémarré, et tout son contenu est à nouveau synchronisé en RAID. Tout ça ne méritait évidement pas un article.

Par contre, j’utilisais jusqu’à présent Owncloud pour synchroniser mes données sur mes différentes machines (je pense d’ailleurs qu’il n’est pas innocent dans la faible durée de vie de ce disque). Et comme le NAS n’avait plus qu’un disque, je ne pouvais plus m’en servir. Coup du sort ou coup du hasard, au même moment, je flânais sur le site de Keybase, et en particulier sur la page dont le titre est « Introducing the Keybase filesystem« . En en lisant les détails, et en particulier la partie « But there’s more », j’ai découvert que je pourrais très bien disposer d’une solution de partage bien plus sûre que ce qu’offrait Dropbox, pour peu que Keybase implémente un système de partage de fichiers. Et comme une bonne partie du code est open-source, il ne tient qu’à moi d’aller comprendre comment ça marche pour proposer un partage … qui fonctionne.

Oh, et en bonus, via un autre ensemble d’urls, il est possible de mettre à disposition du contenu de façon sûre. Idéal pour un site web généré statiquement (donc le retour de JBake).

C’est pas encore demain que je vais virer Thunderbird …

Il y a plus de dix ans, j’adorais tester des clients mails/news : Outlook Express, Opera Mail, FoxMail, XNews, et tant d’autres …

Avec l’émergence des clients web à la GMail, tous ces clients ont peu à peu expiré.

Alors quand j’ai vu ce tweet

je me suis fendu d’un essai … rapide. Rapide, parce que si rambox supporte quelques fournisseurs de mail, c’est à travers leur protocole HTTP, et pas IMAP ou POP. Et ça, ça me choque au plus haut point. Parce que bon, il y a bien un module node-imap, alors pourquoi ne pas s’en service ?

Et j’ai beau chercher, je ne vois pas de feature request pour ajouter imap ou pop. Alors quoi ? Ca n’intéresse plus personne ? Je vais faire le vieux con, mais l’avantage de protocoles comme IMAP et POP, c’est d’assurer une compatibilité instantanée avec un bon paquet de fournisseurs de mails en un coup, ce qui paraît une bonne idée, non ?

Une question de modèle

Je suis tombé sur cette question sur Twitter la semaine dernière

Et aussi curieux que ça puisse paraître, ma réponse est un grand oui.

Si demain un site veut utiliser mon CPU pour miner des cryptomonnaies, ce sera avec plaisir.

Parce que le modèle économique de la publicité sur internet a pour moi des limites terribles

  • Comme il s’agit d’un modèle de l’attention, il limite le contenu visible en garnissant les pages web de bandeaux (animés ou non) de pop-ins et autres instrument réduisant mon écran à un panneau publicitaire géant
  • Comme il s’agit d’un modèle de l’attention, il pousse les sites web vers le titre PUTACLIC, l’absence de contenu réel et une économie de l’attention qui réduit à néant les sites de qualité.

Bon, alors, évidement, ce nouveau mode de fonctionnement a des inconvénients clairs :

  • OH MON DIEU MON CPU EST UTILISE ! (parce qu’un CPU d’ordinateur moderne ne fait rien environ … 95% du temps – statistique à vue de nez)
  • Rien n’interdit à un site web de faire du minage et d’afficher de la publicité

Mais je pense que l’émergence d’une économie utilisant mon CPU d’une façon correcte, au lieu de squatter mon écran, pourrait être intéressante.

Java 9, tu modules ?

Rémi ?

Vous connaissez Rémi ? Il est maître de conférences à Marne la Vallée, développeur d’ASM (j’ignorais ça), d’OpenJDK, expert pour le JCP (et clairement spécialiste des évolutions du langage, pas la partie JavaEE) où il a ajouté invokedynamic, et a travaillé sur les lambda, Jigsaw.

Java 9

Java 9 est la dernière grosse release, parce que c’est pénible. Ca va être remplacé par une release tous les six mois …​ c’est un peu plus rapide. Et donc, dans six mois, on verra var apparaître dans le langage Java.

Les modules

Historiquement, ça devait arriver en Java 6 ou 7 …​ Ca a pris un peu de retard.

Qui veut modulariser le JDK ?

Il y a d’une part des développeurs du JDK qui veulent le faire évoluer, mais ne peuvent pas à cause de toutes les APIs qui utilisent des classes « cachées » du JDK. Et d’autre part …​ des experts de sécurité qui considèrent les failles de la plateforme.

D’autres problèmes

L’enfer du CLASSPATH

Sans outil pour gérer automatiquement le CLASSPATH (genre maven, gradle et autres), c’est l’enfer. Par ailleurs, quand le ClassLoader charge une classe, il scanne linéairement tous les jars et charge la première classe qu’il trouve. Du coup, c’est long. Mais aussi super merdique quand on a deux versions du même artefact. Du coup, on aimerait bien que ce soit géré par la JVM. De la même manière, éviter que les NoClassDefFoundError ne sortent qu’à l’exécution serait une bonne idée pour les développeurs.

Alléger Java

Ce serait sympa de pouvoir faire tourner le code Java sur des plateformes plus légères (typiquement pour l’IoT). Personellement, ça meparaît vaguement possible avec des outils comme ProGuard de limiter la taille des dépendances, mais ce serait mieux d’avoir ça directement dans le JDK. Par exemple, rt.jar contient encore des parseurs XML (qui n’ont pas à être des classes privilégiées) ou CORBA (qui s’en sert encore ?).

Comment modulariser ?

standards
Aucun rapport avec Java, bien sûr

Il y a déja des standards de modules en Java

  • maven
  • gradle
  • JBoss
  • OSGi
  • JavaEE

Du coup, Jigsaw doit fournir un système de modules compatible avec tous ces systèmes prééexistants. Ce qui implique tristement qu’il ne peuvent pas contenir de numéros de version. Et ça, c’est moche.

Modularisons donc !

C’est quoi un module ?

Dans un module, il y a

  • des dépendances
  • et des classes qu’on veut garder invisibles aux autres packages

Par exemple, java se est constitué d’un paquet de modules …​ dont java.compiler. Ce qui signifie qu’il n’y a plus de distinctions JRE/JDK.

Tout ça est décrit dans un module-info.java qui va être compilé comme le reste du code. Ca empêche les modifications ultérieures, ce qui est bien.
A la compilation, il ne peut donc plus y avoir de « split-packages » (des packages déclarés dans deux JARS), ou de dépendances cycliques.

Qu’est-ce qu’on perd ?
  • les « split-package »
  • setAccessible(true) sur une classe d’un module fermé

Au passage, ça permettra enfin à Rémi d’optimiser les champs final (un truc dont j’étais sûr qu’il existait déja pourtant)

Enfin, sauf si on active le flag --illegal-access=permit (qui est parfaitement clair). Notez qu’il y a d’autres valeurs possibles (warn, debug). Bon, un jour, il disparaîtra.

En bonus, les classes JavaEE cachés dans JavaSE (java.xml.bind, java.xml.ws et autres) ne seront plus dans le JDK. Notez que ces classes sont toujours accessibles via des dépendances Maven.
Les classes sun. et com.sun. qui ne sont pas utilisées sont également supprimées.

A noter : L’annotation @ForRemovall (je ne suis pas sûr de l’orthographe) indique les classes qui seront supprimées dans la prochaine version du JDK. C’est une version étendue du classique @Deprecated.

Comment trouver les dépendances

Avec jdeps, par exemple, on peut facilement trouver toutes les dépendances d’un module. Notez que cet outil existe déja dans Java8.

Oui, mais comment je transforme mon application pour Java9 ?

Pour ça, Rémi a développé son application de test : ModuleTools qui lui permet de lire et d’écrire un fichier module-info.java ou module-info.class.Et dans son application, il déclare quelques modules, qui dépendent tous de java.base (comme les classes Java dépendent de java.lang.Object).

Contrairement à maven, un require de module n’est pas transitif (contrairement à maven). Du coup, il y a un require transitif, mais qui est limité à un niveau.

En terme d’organisation de fichiers, il est possible d’avoir plusieurs organisations, dont par exemple plusieurs modules dans le même dossier (ce qui n’est supporté ni par maven, ni par gradle, ni par les IDE).

Il est possible de stocker la version du JAR dans le module-info, et de la réutiliser depuis le code, mais le système de modules n’utilise pas la version.

Comment utiliser un JAR non modulaire ?

Typiquement, une dépendance de Maven Central.On ne peut évidement pas ajouter simplement le JAR dans le CLASSPATH. Il suffit en fait de mettre le jar dans le module-path, et Java va générer automatiquement un module-info, qui permet en plus à ce module automatique de dépendre de JARs du CLASSPATH.Et comment s’appelle ce module ? Soit le nom fourni dans le MANIFEST.MF comme Automatic-Module-Name, soit le nom du JAR sans le numéro de version. Du coup, en ce moment, sur GitHub, c’est la fête à l’Automatic-Module-Name. Au passage, il est possible d’utiliser les JARs modulaires comme des JARs classiques, en les mettant dans le CLASSPATH !

Comment limiter la visibilité ?

Si on veut faire un module interne, il est possible de limiter sa visibilité à certains modules spécifiques, et pas au monde entier. C’est très chouette pour mieux gérer la sécurité. C’est ce qu’ont fait les développeurs du JDK pour la tristement célèbre sun.misc.Unsafe dont une partie a été déplacée dans jdk.unsupported, et une autre partie dans un jdk.internal.misc. Du coup, la réflexion n’est plus possible sur les champs privés (dommage pour gaedo). C’aurait été pénible pour JPA …​ mais les fournisseurs d’implémentation JPA utilisent des agents qui changent le code avant son exécution. Cela dit, la réflexion reste possible grâce à open sur un package ou sur le module.Par ailleurs, le très moche ServiceLoader a été étendu pour fonctionner avec les modules …​ La différence, c’est que la description est un peu propre et intégrée au module-info. Et la description à la fois des fournisseurs d’implémentation et de l’utilisation de ces implémentations doit être fournie. C’est super cool, parce que ça permet de tester les injections de dépendances.

Packager ?

Avec jlink, on peut créer une image à la volée de l’application et de ses dépendances. Pratique pour l’embarqué, évidement, mais aussi pour Docker. Hélas, il ne peut pas y avoir de modules automatiques, parce qu’avec ces modules automatiques, il faut embarquer tout le JDK, et ça limite en plus énormément les possibilités d’optimisation de jlink. C’est un peu la carotte de Jigsaw. Ca permet aussi d’utiliser une JVM minimale de 3 Mo !. Bon, sans JIT, mais sur un Raspberry, c’est pas vraiment utile. Ca permet aussi de garantir la durée d’exécution …​ avec jaotc, qui génère du code natif (qui pourra même se passer de JIT). Le but à terme de cette expérience est (accrochez-vous) de réécrire la JVM en Java (pour se débarasser du code C++).

Evidement jlink (et l’ahead-of-time-compiling) est chouette pour les performances. Et pour l’espace disque.

Conclusion

Modulariser, ça n’est pas si facile, à la fois pour les implémenteurs et les utilisateurs. A ce sujet, la conclusion de Rémi est parfaitement claire : si vous avez une application non-modulaire, n’essayez pas de la modulariser. C’est à la fois long, complexe, et sans valeur ajoutée. En revanche, si vous vous lancez dans une nouvelle application, la modulariser dès le départ peut être utile.

Et merci à nos amis du chtijug pour une soirée sans faille, dans une super salle, et avec une vue vraiment chouette !

Comment est-ce que je gère mes services avec Rancher et Consul ?

Mais pourquoi je veux faire ça ?

Admettons que je veuille me mettre aux microservices … ou plutôt aux services packagés dans des conteneurs docker (quelquesoit la taille des dits services).

Je commence par les packager dans des conteneurs Docker et c’est « cool ». Parce que comme ça, je n’ai pas besoin de demander à l’admin sys de déployer du Java partout, mais du Docker.

Donc, j’ai mes services et mon admin a entendu parler (sans doute sur ce blog) d’un chouette truc qui s’appelle Rancher. Et très vite, il veut ajouter une base de données de configuration (parce que mettre les fichiers de config dans les conteneurs, c’est pas terrible … lisez donc 12 factors apps à ce sujet). Donc il me dit d’utiliser Consul. Et Consul, c’est bien pour la config, mais ça fait aussi service registry. C’est-à-dire que ça permet à un service d’en trouver un autre dynamiquement. Un peu comme du JNDI pour les Javaistes … ou du LDAP pour les ancêtres.

Le problème, c’est que Consul fait service registry, et pas service discovery. C’est-à-dire qu’il peut stocker les services, mais pas découvrir quand ils démarrent ou s’arrêtent (enfin pour l’arrêt, si, mais bon, par symétrie, on va considérer ici que ça n’est pas son boulot).

Et comment je fais pour enregistrer mes services ?

Donc, il faut ajouter un composant d’enregistrement, un « registrator ». Coup de bol, il y en a deux pour Rancher :

  1. Gliderlabs registrator
  2. Rancher Registrator

Pourquoi y en a-t-il deux ? C’est assez bien expliqué dans cette chouette question : Do you kill registrator ? Notez que l’auteur de la question est également l’auteur du second registrator … ceci expliquant cela.

Et ça marche comment ?

D’abord, je vous montre le docker-compose.yml, et ensuite on en discute, ok ?

Dans ce fichier, il y a quelques trucs à noter

Attention à la version !

registrator ne supporte l’option useIpFromLabel que dans la branche master. En ancien développeur Java appréciateur des beaux numéros de version, ça me fait mal, mais bon, on me dit que ça marche comme ça dans le monde de Docker …

internal ?

Ca permet à registrator d’utiliser les ports effectivement exposés par les images, au lieu d’utiliser les ports visiobles hors de Rancher, donc ne l’oubliez pas

cleanup, deregister et resync

La doc de registrator est assez claire, mais ça vaut le coup de bien préciser que ces options sont là pour garantir qu’il n’y a pas de services n’existant que dans Consul (ce qui est un peu bête)

useIpFromLabel

A partir de Rancher 1.2, Rancher utilise un système nommé CNI, ce qui fait que l’ip et le port ne sont plus accessibles via le conteneur Docker mais via le label (ajouté dynamiquement par Rancher) io.rancher.container.ip. Du coup, il faut bien signaler au registrator qu’il faut utiliser ce label pour lire l’adresse du conteneur.

Attention aux labels !

Parce que ce registrator est déployé dans Rancher. Il faut donc qu’il soit présent sur tous les hosts (puisqu’il lit la liste des conteneurs depuius le démon Docker local) (d’où le io.rancher.scheduler.global). Il faut également qu’il ait accès au DNS (d’où le io.rancher.container.dns). Les autres options sont moins indispensables.

Et paf !

Une fois que ces opérations sont effectuées, vos conteneurs seront automatiquement enregistrés dans Consul au démarrage, et supprimés de Consul lorsqu’ils s’arrêtent).