Friday, April 10, 2009

Zenika Wicket Contest / Concours Wicket Zenika

It's exceptional but I wrote this post in french. It's about a contest which proposed to developed a tiny Apache Wicket project with another framework. I tried to implement it with SmartGWT.

Bon et bien voilà : je livre mon appli ZenContact migrée en GWT. Je vous préviens, je ne vais pas trop mâcher mes mots. L'objectif du concours est assez clair : refaire une petite appli de gestion de contacts réalisée à l'occasion d'une présentation Wicket au Paris JUG; le tout avec un petit défi en plus car cette présentation menée par Zenika n'a duré qu'une heure.

Bref, devant l'enthousiasme général, j'ai entrepris de la refaire en GWT. Et comme il fallait aller vite, j'ai choisi de m'appuyer sur des outils et API pour avoir le moins à coder possible. Je fixe rapidement la stack de travail : Eclipse 3.4, Maven 2, SmartGWT. Bon, c'est parti! New maven project -> template gwt. Je teste l'application générée par le plugin Maven. Jusque là tout est OK. Un bonheur.

Je n'ai jamais travaillé avec SmartGWT mais ça a l'air assez riche. Je garde toujours firefox en arrière plan avec la démo de l'API. Je copie-colle des bouts de code et en 3 heures j'ai mon formulaire, mon tableau éditable, le drag and drop, le date picker et tout le reste. Pas mal... Je décide d'arrêter là pour le premier jour.

Le code du tableau triable/editable avec drag and drop : impressionnant non?
contactGrid = new ListGrid();
contactGrid.setWidth(300);
contactGrid.setHeight(224);
contactGrid.setAlternateRecordStyles(true);
contactGrid.setShowAllRecords(true);
contactGrid.setCanReorderRecords(true);
contactGrid.setCanDragRecordsOut(true);
contactGrid.setDragDataAction(DragDataAction.COPY);
contactGrid.setDataSource(this.datasource);
contactGrid.setAutoFetchData(true);
contactGrid.setCanEdit(true);
contactGrid.setEditEvent(ListGridEditEvent.DOUBLECLICK);
contactGrid.setEditByCell(true);


Le lendemain, je passe à l'intégration des pages de l'application Wicket d'origine dont je reprends les 3 fichiers html. Premier problème : j'ai trois pages. Ca fait 3 modules GWT. Pour rappel, pour les petites applications GWT, tout se met dans un seul et même module. Tant pis, je conserve les pages; ça sera l'occasion de me lancer dans la communication entre modules, je ne l'ai jamais fait. Pour cela, j'opte pour une solution pipotesque qui consiste par passer par un cookie. En principe, tout doit rouler car j'ai repéré que SmartGWT travaille tout en JavascriptObject transformables en chaines JSON. Vous voyez où je veux en venir... Et c'est là que les ennuis commencent. Impossible de convertir simplement ma datasource. Je commence à chercher dans la documentation SmartGWT... ah, j'oubliais : il n'y en a pas en dehors de la démo! Je regarde donc du côté de l'API. Le moins que l'on puisse dire, c'est que ça ne manque pas de méthodes. C'est riche, très riche, tellement riche que je ne sais pas quoi en faire. Les petits tours dans le code source me refroidissent vite fait car SmartGWT utilise JSNI à outrance dans la mesure où il ne fait que du wrapping de javascript. Après quelques heures, je trouve la solution. Fin de l'épisode du jour.

Je laisse le projet de côté pendant quelques jours avant de m'y remettre pour le packager. Je reteste quand même vite fait avant. Et là : deuxième problème. Mon tableau n'affiche plus de données. Bizarre. Je m'arrache les cheveux à coup de debugger. Tout a l'air correct.... Je n'y comprends rien. Je recherche du côté de la démo de SmartGWT et me rends finalement compte d'une ligne récurrente dans pas mal d'exemples de code. Un « setAutoFetchData(true) ». Je teste mon code avec ça : bingo! Ca marche! Je réalise à présent qu'en plus d'être trop riche, SmartGWT n'est pas dans un état fini. Je m'imagine dans un contexte de production à chercher ce genre de bug... Bon,avec tout ça, je n'ai pas eu le temps de packager. J'arrête les frais pour aujourd'hui.

De retour sur le code, je redécouvre GWT (je n'en fait plus depuis quelques mois). Pour rappel, 1 module compilé = 1 emplacement pour les fichiers générés. Mais avec mes trois pages, ça ne va pas du tout. Par exemple, WelcomePage.html se retrouve dans tous les répertoires et, comme les liens entre les pages restent relatifs à chaque module, je ne peux pas passer d'un module à l'autre. Bref, je recherche comment faire sur le forum GWT et implémente une petite solution assez simple me permettant de ne travailler qu'avec un seul module.

Enfin, c'est fini! L'application n'est pas complètement bouclée mais je n'irai pas plus loin. Il est d'ailleurs temps d'écrire mes conclusions sur le projet.

Tout d'abord, j'ai été impressionné par les progrès d'intégration des développements GWT dans Eclipse. Cela est clairement dû à l'intégration Maven. Et oui, Maven, on peut dire ce qu'on veut dessus mais c'est tout de même l'esperanto de l'IDE.
Ensuite, j'ai été surpris par la rapidité de prise en main de SmartGWT. La démo est bien faite même si le code source montré n'est pas complet et qu'il faut vite télécharger la suite. Ce framework propose des fonctionnalités très poussées. C'est très agréable... au début seulement. Rapidement, on voit bien que l'API est trop riche. Ca part dans tout les sens. Elle n'est pas guidante et c'est dommage car le code produit au final est plutôt satisfaisant. Cela provoque une courbe de développement chaotique. Au premier bug, c'est l'explosion du temps de développement et la chute de cheveux assurée. Et par dessus cela, comme on est sous GWT, le temps de compilation est (très long) et chaque test devient un calvaire.

Alors, quid de la solution GWT par rapport à la version Wicket? Et bien vous l'aurez compris, je déconseille l'utilisation de SmartGWT pour le moment. L'API n'est pas mature. Elle a toutefois l'intérêt d'être très bling-bling pour les démos. Pour ce qui est de GWT, l'intérêt se situe sur son orientation « client centric ». Et oui, l'application dans sa version actuelle tourne sur un simple serveur Apache lorsque Wicket demande un Tomcat. Mais quelle lenteur ce compilateur Javascript/Java! Finalement, cette expérience confirme l'avis que m'était fait sur ces deux frameworks :
GWT est un excellent framework pour les applications à interactivité utilisateur forte. Ses capacités de manipulations des objets DOM et de gestion des évènements du navigateur sont excellentes.
Dans le cas d'une application de gestion classique, Wicket est un choix bien plus judicieux. L'utilisation des « Model », la gestion des conversations, le développement loin de javascript (qui est quand même un vrai langage de merde!), l'intégration Spring, l'internationalisation, le code source clair sont autant de points qui font du développement avec Wicket un vrai bonheur.

Pour finir en quelques mots : Wicket c'est une Renault. Ca marche plutôt bien au quotidien. GWT, c'est une Ferrari. C'est beau une Ferrari. La super éclate le week-end. Mais pour aller chercher le pain, ce n'est pas forcément le mieux.

Télécharger le projet compilé (à dézipper + trouver le WelcomePage.html) : zencontact_gwt.zip
Télécharger le code source : zencontact_gwt_src.zip

2 comments:

hoani said...

Salut ! C'est du bon boulot, je suis un ancien utilisateur de Wicket, j'ai tout de suite adopté. J'ai découvert SmartGWT récemment avec XWiki et j'ai trouvé ça puissant (l'effet démo). Je suis sur le point de tester l'intégration des deux et ton article va beaucoup m'aider. Merci.

Rahul said...

Thanks for the great information in your blog Selenium Training in Chennai