Google App Engine for Java : a real voyage in the Cloud
Cette deuxième journée Devoxx Université débute par 3 heures sur Google App Engine. En fait cette présentation était une revue de code d’un projet développé sur Google App Engine par Sam Brodkin et Scott Stevenson. Nous avons parcouru le code, tout en regardant le résultat de l’application développée en temps réel. A noter que la session a été très participative. L’ensemble de la salle a navigué sur le site, ce qui était plutôt vivant.
L’application SwagSwap
Scott débute la présentation en expliquant le but de son application, SwagSwap. Tout d’abord un Swag, c’est un de ces petits cadeaux que l’on vous offre lors des conférences. Tee-shirt, stylo, autocollant, poster, bref tous les goodies qui font le bonheur des Geeks. L’objectif de l’application SwagSwap est de permettre à chacun de lister les goodies de la conférence, puis de noter et de commenter les cadeaux offerts pas les sponsors. L’application est en ligne à l’adresse http://swagswap.appspot.com sur Google App Engine. Sujet plutôt sympa pour débuter la journée.
Un slide me fait sourire, où Scott littéralement propose à l’audience 5 niveaux de participation :
– Faire le Zombie : vous restez assis là pendant 3 heures sans rien faire
– Bug Patrol : vous recherchez et vous loguez les bugs trouvés dans SwagSwap sur le site Google Code du projet
– Lurker : vous téléchargez le code, vous le regardez mais vous n’y contribuez pas
– Inquisitor : vous posez des questions de manière interactive ou via le site Google Moderator qu’ils ont mis en place
– Contributor : vous ajoutez une nouvelle fonction ou vous fixez un bug pendant les 3 heures.
Scott commence ensuite sa démonstration de SwagSwap. L’interface sommaire à la Web 1.0 est développée dans la version qu’il sélectionne avec Spring MVC. En fait, Sam Brodkin a codé une version Spring MVC, une version GWT. Scott Stevenson a codé une version JSF2. La suite de la présentation sera largement consacrée à une comparaison pointue des 3 solutions, ce qui est plutôt intéressant pour nous.
Quelques mots sur Google App Engine
A moins d’avoir fait un stage chez les Mormons, vous ne pouvez pas me dire que vous n’avez pas entendu parler de Google App Engine. En quelques mots, c’est la solution PaaS (Platform as a Service) de Google pour faire tourner dans le Cloud une application Web Java. GAE (Google App Engine) utilise Jetty, et permet de faire tourner avec quelques limitations, une application java. Les avantages de la solution : plus besoin d’installer une infrastructure, même plus besoin de s’amuser avec des images comme avec Amazon EC2 (voir mon article de lundi). Google monte en puissance pour vous, de manière transparente. Vous ne payez que l’usage réel. Et chose très intéressante, Google ne vous fait payer le service que lorsque vous dépassez un seuil d’utilisation des ressources. Il est donc possible de démarrer un projet sur GAE et de ne rien payer.
Google App Engine propose une console d’administration Web qui permet de suivre la consommation de son serveur. Il est aussi possible de voir les Entités de son domaine, de régler quelques paramètres de son application.
Il y a cependant quelques limitations qui font qu’il sera peut-être impossible pour vous d’utiliser GAE. Tout d’abord le temps d’une requête Web est limité à 30 secondes. Au delà, Google coupe la connexion. Il n’est pas possible de faire tourner vous-même des tâches de fonds, ni des Threads sur le serveur. Vous n’avez en fait jamais accès à une machine, vous vous contentez de déposer votre WAR avec les outils de Google, c’est tout. Donc pas d’installation de logiciels possibles. Il n’y a pas de serveur Push, le système de fichier est considéré comme étant en lecture seul. Il n’est donc pas possible de sauver un fichier temporaire. Pour envoyer une image vers le serveur, il faut donc ruser et travailler en mémoire avant de stocker l’image. Enfin le point le plus important : vous n’avez pas accès à toutes les classes Java. Google donne une liste blanche des APIs autorisés. Par exemple il n’y a pas d’API Swing, donc il est impossible de retravailler des images sur le serveur. Pour la démo de SwagSwap, ils ont donc utilisé un service de Google pour créer des Thumbmails sur la page d’accueil. Bref tout ceci pour vous dire qu’il y a quelques sacrifices à faire pour que tout fonctionne.
Le développeur travaille en local avec une émulation de Google App Engine. Des plugins pour IDEA IntelliJ et Eclipse permettent de packager et d’envoyer vers GAE votre archive, lorsque vous souhaitez faire une mise en production.
La base de données
Les données sont stockées avec BigTable. Le DataStore de GAE est un moteur basé sur un noyau hautement distribué, capable de monter en charge, transactionnel et sans schéma. En fait, BigTable c’est une énorme Hashtable dans le Cloud. GAE supporte JDO et JPA, mais les démonstrations ont été écrite avec JDO, qui semble mieux documenté d’après les speakers.
L’application de base
Le coeur de la partie Service est implémenté avec Spring 3.0, JDO, les transactions et un peu de RESTful avec Spring Web MVC. Ensuite, 3 GUIs différents ont été implémenté. La version Spring MVC a demandé 3 jours de travail. C’est une application Web 1.0 plutôt bien écrite de ce que j’ai vu. La version GWT 1.7 a demandé entre 3 et 4 semaines d’efforts. Il y a cependant un gros travail sur l’ergonomie. Sam a utilisé SmartGWT pour créer une interface plutôt sympathique. Enfin la version JSF2 a demandé 5 semaines, et toutes les fonctions n’ont pas été implémentées. Il a encore peu de projet avec JSF2 sur GAE, donc Scott a pas mal travaillé. Mais le résultat est sympa.
Pour compiler et déployer le projet, ils ont utilisé Ant. Le support de Maven2 et de GAE d’après eux, ce n’est pas encore cela. Concernant la gestion du code source et les tickets d’incident, le tout est sur Google Code.
La sécurité
Les utilisateurs sont authentifés avec les services de Google. Le code est très simple, et il est facile d’appeler les services de Google. Pour protéger les pages, Spring MVC et les filters permettent de déclarer les URLs qui demanderont de l’authentification. L’application a aussi un objet SwagUser avec par exemple les votes et vos commentaires. Cet objet est créé lorsque l’utilisateur s’authentifie la première fois sur l’application. Il est ensuite simplement rechargé si vous revenez. La clé primaire utilisé n’est pas l’email Google mais le Google Account Name. En fait, Sam a découvert que la version GWT envoyait vers le client la liste des emails des personnes ayant postées un Swag sur le site, plutôt genant.
L’accès aux données
Concernant les données, un tour dans la classe ItemDAO nous montre que le code est plutôt simple. Ils utilisent Spring JDOTemplate, avec un persistenceManager. Les Transactions sont aussi utilisées, mais j’ai vu des méthodes synchronized (comme updateRating). Bizarre.
Un souci de Google App Engine et du modèle de persistence : il n’est pas possible de faire des recherches sur plusieurs Entités à la fois. La recherche sur les champs textes est aussi forcément Case sensitive… Bref si vous voulez ajouter un champ « Search » sur votre application GAE, le mieux est de vous tourner vers un projet comme Compass. Celui-ci se place au dessus de Lucene. Il indexe les entités et permet de faire de la recherche full-text sur des Entités. Très pratique, je m’en suis servi sur http://touilleur.appspot.com (projet non terminé).
Concernant l’authentification, si vous cliquez sur un lien dynamique (GET /view/item?order=toto) et que vous devez passer par la page d’authentification de GAE, la QueryString n’est pas conservée. Il y a un bug sur App Engine (bug 2225) à ce sujet.
Spring MVC
Des 3 frameworks utilisés, c’est le plus simple et le plus pratique. Nous avons passé un bon bout de temps dans le code. Cette partie était trop axée Spring, et plus tellement GAE. Mais bon, si vous ne connaissez pas encore Spring MVC, il faut vous y mettre. Les annotations et la gestion des RequestMapping par exemple, c’est fort.
Google Web Toolkit 1.7
La version GWT est clairement très Web 2.0. Mais ce que j’ai retenu c’est que trop de Web 2.0 c’est plutôt fatiguant. D’un point de vue applicatif, il n’y a pas grand chose de plus. Oui de l’Ajax, ok. Mais j’ai été un peu inquiet de voir la quantité de code pour un résultat qui n’est pas si énorme que cela. De plus avec 1000 fichiers dans cette petite application, je trouve que l’on se rapproche trop de la limite des 3000 fichiers statiques par application Google App Engine. Du côté de GWT, le framework SmartGWT est vraiment propre. Rien à voir avec cette bouse de GWT-Ext qu’un client aux USA veut utiliser…
La gestion des images
L’application vous permet d’uploader vers le serveur une photo du Goodie, afin de l’afficher sur la page d’accueil en vignette, et en grand sur la page détaillée du Swag. Mine de rien, cette partie sur le traitement de l’image, pour GWT, JSF2 ou Spring MVC, représente un gros boulot par rapport à une application classique.
Sam présente tout d’abord le service de Google qui traite les images, les retaille et vous les redonne. Plutôt bien fait je trouve. Comme il n’est pas possible de stocker les images dans un répertoire, il faut écrire une Servlet qui stream le contenu de l’image vers le navigateur. C’est pas top je trouve. Hier la démo d’Amazon avec le service Amazon S3 pour stocker les images m’a semblé bien plus pro que ce que j’ai vu là. Cela donne des URLs super sexy pour récupérer une image dans l’application. Jugez plutôt:
<img src="<c:url value='/springmvc/showimage/${swagitem.imageKey}'/>" />
Bien entendu, cela pose aussi des soucis avec le cache du navigateur… Si l’image change, le navigateur ne rafraîchit pas l’image. Il semble qu’il ne soit pas possible de changer les headers HTTP et de faire expirer le cache… Je n’ai pas posé la question.
Qu’est-ce qui marche sur GAE ?
La liste des classes Java est limitée. En conséquence, tout les frameworks Java ne fonctionnent pas sur GAE. Par exemple Grails par défaut déclare un log4j avec un FileAppender… ce qui est interdit sur GAE. Regardez cette page pour vous donner une idée de ce qu’il est vraiment possible de faire sur GAE:
Will it play on Google App Engine ?
JSF2.0
Là j’ai décroché… Ce que j’ai entendu c’est que c’est faisable, mais difficile. Les slides enchaînent les soucis et les limitations, de quoi déprimer. Mais le résultat est plutôt sympa concernant l’interface utilisateur. Le code source dans la partie Java est propre, comparé à la soupe de la version GWT+SmartGWT. Bon si vous voulez voir ce que donne JSF et Google App Engine, le mieux est de télécharger le code du projet et de regarder par vous-même
Autres trucs cités
Scott parle aussi du service d’envoi des emails de Google App Engine. Pratique et simple à utiliser, limité à 1000 mails par jour. Ils effectuent aussi une démonstration de la mise en production sur l’App Engine : simple et clair comme les autres projets Google. Concernant l’asynchronisme, il est possible de configurer des Jobs pour appeler une URL donnée avec une syntaxe à la Cron. Pas du JMS, mais pratique pour envoyer par exemple un email à minuit aux abonnés du site.
Une question sur la gestion des backups : il y a un projet appelé GAE bar http://aralbalkan.com/1784
Conclusion
En sortant de la présentation, j’ai trouvé que la partie Spring du côté service était vraiment intéressante et adapté à Google App Engine. La version GWT+SmartGWT demande quelques efforts de programmation mais semble plutôt bien écrite. La version JSF2 m’a déprimé et me semble encore trop jeune par rapport à l’architecture de GAE pour l’instant.
Google App Engine est très certainement une plate-forme intéressante. Attention cependant à bien se rendre compte que cette plate-forme demande un investissement assez important afin d’apprendre à écrire un modèle de données sans schémas. De nouveaux problèmes apparaissent comme ce cas de la gestion des vignettes du site. Ne pas pouvoir stocker un fichier sur un disque, cela vous force à chercher d’autres solutions.
Nous manquons encore un peu de recul, mais ce projet est un très bon point de départ si vous cherchez un exemple complet d’application sur Google App Engine. J’aurai aimé une version Groovy pour comparer, avec Grails ou Gaelyk par exemple.
Voilà je n’ai pas tout couvert, mais Romain de Xebia était aussi là, et donc le blog de Xebia vous donnera un autre angle sur ce sujet.
Références
Page du projet SwagSwap sur Google Code
Page d’accueil sur Google App Engine de SwagSwap
La version Spring MVC
La version JSF2
La version GWT 1.7
Bonjour,
GWT-EXT, c’est un wrapper de EXT-JS qui est abandonné. Il est donc préférable de l’oublier.
SMART-GWT, c’est un wrapper de Smart Client qui propose pleins de widgets mais fourvoie un peu le concept de GWT à mon sens.
EXT-GWT (GXT) reste plus dans la philosophie de GWT mais reste encore perfectible (dans son code et son processus de mise à jour)
Je n’ai pas regardé le code, mais même si elle reste limitée, je trouve cependant la version GWT plus fun à utiliser (pour le peu que j’ai testé)
Spring MVC ou JSF, ça ressemble à des applications d’il y a 10 ans. Et si je suis d’accord qu’il ne faut pas abuser des effets, AJAX contribue à faire des applications plus user friendly.
Bonjour,
En ce qui me concerne, mon expérience avec smartGWT me laisse sur ma faim.
Je l’ai pris essentiellement pour avoir un datagrid correct.
Et aussi pour avoir une apparence de base plus actuelle.
Le principe est que l’intégration GWT-SmartGWT fonctionne le mieux quand c’est un widget GWT qui est en bout de branche. Et que la branche est écrite en smartgwt.
Exemple : On doit utiliser non pas VerticalPanel mais VLayout. Ca c’est du structurel.
J’ai eu des problème de z-index avec des panels dans des onglets. Conséquence : devoir réagir au changement d’onglet (rendre invisible TOUS les autres, bonjour la maintenance). Ca c’est un bug.
Mon expérience remonte à la version 1.1 et j’imagine que les bugs sont corrigés. Par contre, le structurel et l’adhérence forte à cette API sont forcement toujours d’actualité.
Nicolas, thanks for this nice writeup of our talk and for your compliments!
You make a good point about the synchronized method inside the transaction. Silly that I didn’t catch that. Thanks for pointing it out.
About the image caching problem, i tried expiring the HTTP headers but that didn’t seem to work. Could have something to do with the SmartGWT DataGrid (that’s the only place the caching problem showed up). So I was forced to rewrite the URL.
You called the GWT impl soup. I agree. I wasn’t sure how to make it less soupy. Anyone have any quick suggestions? Here’s the mega class: http://tinyurl.com/SwagSwapGWT