Retour du meetup GWT 2015 à Google

GWT 2.8 3.0 JsInterop APT GSS Generator

Arnaud Tournier, le 10-06-2015

Ces derniers jours se déroulait à Google, Mountain View, le meetup annuel de l’équipe GWT. Une occasion pour tous les acteurs et contributeurs importants de se réunir et de faire le point sur l’état du framework, et surtout sur son futur.

Vous lisez un résumé de ce rendez-vous. Vous y apprendrez tous les secrets et tout ce qui se trame pour la version 3.0.

La plus grosse nouvelle pour la plupart d’entre vous va surement être la disparition des Widgets. Apprenez-en plus ici, et préparez votre futur !

Après lecture, vous saurez comment faire évoluer votre application GWT pour vous préparer aux nombreux changements (cassants) qui vont arriver en version 3.0 !

GWT 2.8 et ensuite

(présenté par Ray Cromwell et Goktug Gokdogan)

GWT 2.8, où en est-on ?

Voici le périmètre de la version 2.8 :

  • Java 8, toutes fonctionnalités implémentées,
  • JsInterop,
  • GSS,
  • System.getProperty() : importer statiquement des valeurs passées au compilateur à la compilation (remplacera les permutations en version 3.0),
  • Performances et bug fixes (type tightener par exemple).

Aujourd’hui, on est à 80%/90% de réalisation de l’objectif. Mais il y a encore des bugs avec les lambdas et les nouvelles reference methods de Java 8.

Au niveau de l’émulation, les packages java.util.function / java.util.stream ne seront pas émulés et l’équipe de GWT espère que la communauté prendra en charge cette partie.

JsInterop

Il y a eu des changements dans la spécification, qui est d’ailleurs toujours en mouvement. Mais le tout est dans un état de finalisation.

Et après ?

GWT a dix ans cette année. Le contexte a complètement changé depuis sa création. Il y a maintenant de nombreux frameworks UI de qualité comme React, Angular, Amber, Typescript, et tant d’autres outils puissants. Les mobiles aussi ont émergé. En fait il faut trouver un moyen de faire levier sur tous les outils javascript qui existent aujourd’hui, et qui d’ailleurs n’existaient pas à l’époque.

Qu’est-ce que GWT ? Il fait tant de choses !

GWT est en fait tant de choses. C’est :

  • un transpileur
  • un optimiseur de code javascript
  • un processeur d’annotation
  • un système de build
  • un environnement runtime
  • une bibliothèque UI

En fait GWT supporte une complexité trop importante, surtout si l’on considère les outils standards qui existent par ailleurs et qui pourraient prendre le relais. Par exemple APT peut prendre le relais sur les générateurs. Pour les systèmes de build, il y a Maven, Gradle, Bazel, … Pour les permutations, il y a le nouveau System.getProperty().

Il faut également adapter la sortie du compilateur GWT aux futurs modules ES6. Et faire levier sur le compilateur closure compiler. En faisant la comparaison, on s’est rendu compte que si on désactivait les optimisations faites par gwt, closure produisait des fichiers js de taille équivalente. Il est donc peu risqué de désactiver les optimisations GWT et laisser le travail à closure.

Par ailleurs, il faudra aussi faire levier sur les apis des navigateurs (à travers elemental, jsinterop et definitely typed).

Directions futures

La vision directive est que les mondes Javascript et Java doivent fonctionner naturellement ensemble.

De plus, le compilateur doit être rapide, et conceptuellement plus simple pour faciliter sa maintenance et son évolution.

Ce qui va casser avec GWT 3.0

  • Les Widget seront complètement abandonnés (elemental, JsInterop ou autres systèmes de widgets).
  • Gwt-rpc aura également disparu en version 3.0. Il faudra plutot utiliser l’ajax pur et json.
  • JSO et JSNI vont être abandonnés.
  • Ne plus faire de générateurs, utiliser APT, ou System.getProperty() à la place du deferred binding.
  • GWT.create, c’est fini !
  • Finies aussi les permutations “user-agent”. Il faudra utiliser les properties systeme “user-agent” fournie par les paramètres de compilation. La valeur sera toujours résolue à la compilation et donc optimisée.

Et que va-t-il rester ?

  • Les fondamentaux :
    • L’émulation de la BCL Java,
    • JsInterop,
    • Elemental ou équivalent
  • Utilisation accrue de bibliothèque tierces :
    • Singular,
    • Polymer,
    • React,
    • Angular
  • APT à la place de la génération de code GWT
  • Utilisation de System.getProperty().

Pourquoi tout cela ?

Les gens se plaignent de la lenteur de la compilation. John Stalcup a travaillé pour améliorer les performances. Le SDM transcrit en JS avec un nommage stable, sans optimisation. Et il recompile seulement ce qui a changé.

Mais comparé à un compilateur C ou Java, le compilateur GWT est tellement compliqué. Ainsi, rentrer dans le code peut prendre des années. Même pour Ray, parfois corriger un petit bug peut prendre beaucoup de temps.

Et le fait est qu’il serait interressant de pouvoir profiter des frameworks modernes et populaires comme React, Singular, Angular…

De plus, GWT a été conçu pour créer des applications monolithiques. Avec GWT 3.0, on aura une compilation plus modulaire, avec des mécanismes similaires aux module ES6, ou aux class loaders de Java.

Donc GWT va s’aligner avec la façon dont les applications JS fonctionnent (Async modules par exemple). Et du coup le compilateur va devenir beaucoup plus simple, donc plus réactif, plus performant et plus facile à maintenir. Très bonne nouvelle.

Le système de Widget :

Pourquoi pas le porter en JsInterop, ca serait faisable, mais plutot pour maintenir des applis. Ca ne serait pas du long terme.

En gros, simplement maintenir GWT tel qu’il est serait voué à l’échec. Il faut un changement de cap ! C’est un peu radical, mais la médecine est nécessaire.

La prochaine génération de compilateurs Java vers JavaScript

(présenté par John Stalcup)

Afin de dérisquer la vision évoquée précédemment, un prototype de nouveau compilateur a été développé. C’est un simple transpileur Java 8 vers Javascript. Il ne fait aucune optimisation (ce sera le role de Closure compiler qui sera exécuté en fin de chaine). Aucun mécanisme de génération ni d’injection de dépendances. Ceci sera fait par le build système, et aussi par APT.

Les données en entrée sont toujours les fichiers source Java. GWT.create() sera inutile. Ce compilateur est entièrement focalisé sur la productivité du développeur.

La priorité est de pouvoir itérer rapidement. Inbox et Google Docs sont des gros clients. Les cas d’utilisation de GWT seront toujours les deux suivants :

  • pouvoir réutiliser du code logique métier Java dans une application client.
  • pour ceux qui aiment simplement Java et veulent développer des applications web dans ce langage.

Expérience IDE

L’expérience IDE devrait être conforme à une utilisation classique en Java. Par exemple, en Java les fichiers .class sont générés à la volée. Ce devrait être identique pour les fichiers .js.

Donc cela sera surement plus simple pour l’utilisateur. Et aussi pour le développeur du transpileur (plus besoin d’un mode Super Dev Mode…).

Faire levier sur l’écosystème Javascript

Avec closure, on aura une très bonne optimisation. Il y a d’ailleurs dans closure un mécanisme de permutations assez similaire à celui de GWT. Closure par défaut produit une seule permutation, mais il est possible de spécifier certaines propriétés qui doivent générer des fichiers JS spécifiques à la valeur de la propriété au moment de la compilation.

Le compilateur GWT générera du Javascript ES6 très lisible. Les champs des classes seront directmeent déclarés dans les constructeurs Javascript, de façon à laisser les VM Javascript optimiser le code Javascript de la meilleur façon possible.

ES6 et sont système de module

Ce système est assez similaire au class loading de Java.

  • le name mangling doit rester pour supporter la sémantique Java (polymorphisme, méthodes virtuelles, constructeurs multiples, …)
  • les classe literals n’existent pas en Javascript.

Des exemples de codes Javascript générés avec ce nouveau compilateur sont montrés, et il est vrai que le javascript est tout à fait lisible et compréhensible.

Architecture

Ces trois derniers mois ont été consacrés à prototyper ce nouveau compilateur. Le futur est donc déjà en marche !

Toutes les options ont été envisagées pour réaliser ce nouveau compilateur (écriture from scratch, utiliser le code de J2Objc, faire évoluer le compilateur actuel, utiliser d’autres compilateur Java->JS qui fonctionnent sur le byte code). La décision a été de réécrire le tout.

Les solutions utilisant le bytecode java comme entrée ne permettent pas à priori d’obtenir les meilleures performances, mêmes si elles permettent d’ouvrir GWT aux autres langages s’exécutant dans la JVM (Scala, Groovy, …).

Compilation

Pour compiler le Java, pourraient être utilisés JDT ou Javac. Ou bien on pourrait écrire un compilateur de zéro, mais trop long.

Donc l’architecture sera plutot :

  • JDT comme processeur et générateur d’AST
  • Transformation en AST GWT
  • Transpilation immédiate en Javascript.

C’est tout !

Comme vous le constatez, l’architecture est réduite à son strict minimum. Ce qui pour moi montre que l’équipe GWT a su extraire l’essence de GWT et qu’elle a su tirer les leçons du passé. Tout ceci montre que l’avenir de GWT est entre de bonnes mains.

Mode de génération des fichiers Javascript

Les choix ici sont critiques quant à la qualité des fichiers Javascript générés. Heureusement, l’équipe dispose d’ores et déjà de benchmarks qui permettront de bien évaluer les décisions architecturales prises.

A faire autour du nouveau compilateur

  • Rédaction de l’ensemble des sémantiques Java, de façon à implémenter rapidement quelque chose qui implémente la sémantique Java.
  • Un sous-ensemble de la JRE doit être émulé. On utilisera surement un version modifiée de la couche d’émulation actuelle.
  • IO et Thread seront toujours proscrits. Pour la réflection, la décision n’est toujours pas prise. Peut-être un sous-ensemble de l’API de réflection ? Le sujet reste ouvert, mais ce qui est sûr c’est que ce sujet a un impact très important sur les performances.
  • Une api DOM minimale.
  • JsInterop. Une bonne partie de la logique de JsInterop existe déjà dans Closure et pourrait donc lui être déléguée.
  • Intégration avec Bazel.

Performances

En terme de performances, voici les objectifs fixés :

  • taille des fichiers générés. En générant du code Javascript compréhensible par Closure, la taille des fichiers générés est estimée à 25% en dessous de ce qui est généré actuellement avec GWT.
  • vitesse d’exécution. En fait au lieu d’optimiser le Javascript, le mieux est d’éviter de perturber les VM Javascript (ce qui est le case avec les optimisations faites par le GWT actuel). La politique d’optimisation GWT change fait donc un virage à 180° !
  • rapidité du transpileur. Cela doit être comparable à la compilation Java à la volée dans Eclipse, c’est-à-dire imperceptible.

Préparer vos applications à GWT 3.0

(présenté par Daniel Kurka)

Comment programmer des applications GWT aujourd’hui de façon à ce qu’elles soient encore compatibles avec GWT 3.0 ?

Les générateurs, permutations et JSNI vont être abandonnés.

GWT fait trop de choses !

  • build system,
  • optimizing compiler,
  • biliothèques intégrées (GSS, …)

GWT a un énorme écosystème. Mais le contexte dans lequel GWT est né n’est plus valable. GWT est populaire pour ses performances mais est détesté pour sa lenteur de compilation.

Si l’on réfléchit aux permutations, ce n’est pas vraiment un job pour le compilateur.

Le Rebinding

Replace-with

Aujourd’hui on utilise <replace-with>. Mais ceci va complètement disparaitre. A la place il faudra écrire (par exemple) :

private static HistoryImpl impl = createImpl();

private static HistoryImpl createImpl()
{
	String userAgent = System.getProperty("user.agent");
	return "ie8".equals(prop) ?
		new HistoryImplIE8() :
		new HistoryImpl();
}

Ceci est tout-à-fait équivalent ! Et cela permet de déléguer la problématique des permutations au build system.

Notez que l’implémentation de System.getProperty() sera disponible en GWT 2.8, donc les applications auront la possibilité de se préparer en avance de phase au passage à la version 3.0 !

Ce nouveau paradigme aura l’avantage de vous permettre de grouper vos permutations à votre guise.

Génération de code

Les générateurs posent problème :

  • “Donne moi toutes les classes qui implémentent l’interface X” est le genre de question que l’on peut poser au sein d’un générateur GWT. Mais ceci pose trop de problèmes pour écrire un compilateur incrémental.

APT qui est un standard Java propose pratiquement les mêmes fonctionnalités. Certes l’API d’APT n’est pas la panacée mais certains projets peuvent aider dans ce sens : google auto, dagger, dagger 2, immutables, hexa.binding

Quelques problèmes néanmoins avec APT :

  • l’API n’est pas terrible (c’est le moins que l’on puisse dire, et de ma propre expérience je confirme !).
  • si le generateur APT utilise une resource, il n’est pas déclenché si cette resource est modifiée, seulement quand un fichier Java est touché. Solutions posibles : avec Bazel ceci peut être prise en charge par le build system. Avec Maven, ceci prendrait quelque chose comme 10 secondes par itération : insupportable. Gradle : 3 secondes, toujours mauvais. Une solution (un serveur de dépendance) pourrait être que le générateur APT emette un fichier dans lequel il décrit tous les fichiers resources utilisées, puis que le build system consomme ces fichiers et s’en serve pour déclencher le processeur d’annotation au bon moment.

Pour l’instant, voici les générateurs internes à GWT qui pourraient fonctionner en étant portés pour APT :

  • GSS et ClientBundle,
  • I18N,
  • UiBinder,
  • SafeHtmlTemplates,
  • PlaceHistoryMapperGenerator.

Mais un générateur pose de gros problèmes : GWT RPC. Il faudrait avoir plus d’informations dans les interfaces de service pour que le générateur puisse fonctionner en mode “APT” avec les bonnes informations, sans avoir à connaitre l’ensemble de la base de code de l’application (ce qui empêche toute sorte de compilation incrémentale efficace).

GSS et I18N seront surement portés vers APT.

I18N

Celui-ci aussi sera porté. Il consommerait toujours des fichiers de property mais générerait plusieurs fichiers java en une seule fois. Puis on utiliserait System.getProperty() pour sélectionner l’implémentation, ce qui permettra d’éliminer les implémentations non nécessaires à la compilation.

L’ensemble générera une factory à la place d’avoir à être utilisé avec GWT.create().

Une interface I18N ressemblera probablement à ceci (assez proche de ce que l’on a aujourd’hui) :

@Translate({"de", "fr", ...})
public interface MyTranslations // plus d'interface de marquage
{
	String hello();
}

Pour l’utiliser, la génération APT fournira une factory que lon pourra appeler ainsi :

MyTranslations instance = MyTranslations_Factory.create();

Comme vous le voyez, la migration ne sera pas traumatisante !

GWT RPC

Cet outil a eu beaucoup de succès car très transparent, presque “magique”. Mais il ne peut pas compiler efficacement car il a besoin de connaitre l’ensemble des classes de l’application.

GWT RPC sera donc abandonné. Sans doute en faveur de Protobuffer, ou Rest. Mais le remplaçant n’est pas encore choisi !

Accès DOM

Si l’on regarde de près, les classes de gwt-user utilisent fortement JSO et JSNI, qui vont être abandonnés. Comme JSO et JSNI ne seront plus disponibles en 3.0, gwt-user sera complètement inutilisable !

Il faudra donc préférer les framework javascript à intégrer avec JsInterop :

  • Polymer,
  • React,
  • Angular,
  • Singular,
  • Tardigrade…

Singular, état

  • le coeur est stable (on peut écrire des directives),
  • le Singular expression language est implémenté,
  • mais la sécurité doit être auditée.

Pour résumer

GWT est là depuis 10 ans et a pris les bonnes décisions. Mais il faut maintenant envisager les dix années suivantes afin que GWT apporte toujours une valeur importante. Cette refonte apporte des changements majeurs et cassant pour la maintenance de vos applications.

En fin de compte, intégrer des Web Components se fera très facilement, avec une cuiller à pot. La migration de votre application vers la version 3.0 sera une tâche parfois ardue, mais nécessaire quand on considère toutes les innovations dont va bénéficier la nouvelle mouture de GWT. Il est impératif de préparer dès maintenant votre application, de façon à assurer votre futur. Côté GWT, google prend les choses en main.

LTE Consulting est une société experte sur la technologie GWT. N’hésitez pas à nous contacter (ltearno@gmail.com) si vous avez besoin d’aide pour votre projet !


Arnaud Tournier, le 10-06-2015