Rha la freebox !

Bon, je ne vais pas vous parler du fait que la freebox va enfin passer à Android TV, parce que ça n’est qu’une rumeur (même si c’est une rumeur très intéressante).

Non, je vais vous parler du problème classique des freenautes : les petits détails gênants. En l’occurence, le détail gênant, c’est la gestion de la surchauffe apr la freebox revolution server. Ou plutôt, dans mon cas, sa non gestion.

Voyez-vous, j’ai récement légèrement réaménagé mon salon : j’ai remplacé une jolie étagère Fly sur laquelle était posée la Freebox Server par une bibliothèque Billy que j’ai légèrement améliroé en y forant des trous pour passer tous les câbles de la freebox derrière le meuble, ce qui est moins disgracieux (j’en connais qui parleraient de WOF, mais soyons sérieux, je trouve les câbles électriques ou réseau d’une laideur abyssale). Et il semble que le fait de placer ma Freebox Server dans une bibliothèque nuise gravement à ses performances, ou plutôt à son aération, puisque depuis ce changement, je perds l’utilisation d’internet, de la télé ET du téléphone à peu près tous le sjours.

Insupportable.

J’avais d’abord accusé le transformateur CPL, mais même en le mettant plus à l’air, rien n’y fait, les déconnexions continuent. J’ai donc le choix entre

  • ouvrir la freebox pour l’aérer (facile à faire apparement mais un peu sale sur le long terme),
  • tenter de la poser sur une plaque métallique elle-même ventilée avec un ventilateur USB par exemple
  • la déplacer vers un endroit plus aéré

J’ai bien l’impression que je vais choisir la troisième solution …

Cela dit, il y a là un autre élément gênant.

Quand j’ai quitté le googleverse, j’ai installé un paquet de servcies sur mon NAS (qui marche très bien, lui). Parmi ces services, on peut évidement compter shaarli, krissfeed et deux ou trois autres trucs Indispensables au travailleur du savoir que je suis. Problème : aucun de ces services n’est accessible aujourd’hui, puisque ma freebox s’est arrêtée !

Et ça, ça s’appelle un Single Point Of Failure ou je ne m’y connais pas …

Ce qui me rappelle furieusement le projet Chaos Monkey de Netflix : si on veut savoir comment se comporte un système quand un composant, il n’y a qu’une seule bonne façon de vérifier : en débranchant le composant pour voir ce qui se passe.

Javascript all the things .. or not ?

Depuis deux semaines, je me suis remis avec intensité (et sous la contrainte)  au développement Javascript dans un univers proche du navigateur classique, mais pas tout à fait semblable.

Et je dois dire que, si certaines choses ont changé, d’autres sont toujours aussi décevantes.

Typiquement, je suis déçu d’avoir passé DEUX JOURS ENTIERS pour détecter que je passais un argument undefined à une fonction. Surtout que c’est arrivé alors que j’utilise Eclipse avec son mode Javascript, qui est censé m’afficher quelques erreurs (mais qui n’est apparement pas dérangé par l’utilisation de variables non définies … à moins que ça ne soit configurable).

L’autre déception, mais je m’y attendais, c’est nodeJS et son écosystème authentiquement merdique. Je m’explique.

Vous pensez que nodeJS est un framework permettant de développer des applications web côté serveur, pas vrai ? Moi, en tout cas, je le croyais. Jusqu’à ce que je découvre que, via NPM, Grunt, Bower, et tout un tas de projets concurrents aux noms de hipsters mal dégrossis, les développeurs Javascripts sont censés être capables d’en faire l’équivalent de maven. Sauf que, d’une part, personne ne s’est dit "tiens, si on faisait tourner maven dans Tomcat ?", et que d’autre part le tri évolutif n’a pas encore lieu : il y a pour chaque besoin au moins deux outils concurrents, à peu près aussi peu fiables l’un que l’autre, et toujours très mal documentés. En bonus, quand vous commencez un projet, que node commence par installer tout un tas de trucs sur votre machine, et que le fichier package.js ne semble pas vraiment utilisable pour ajouter des dépendances (on me dit toujours de faire npm install bidule), ben ça fait bizarre.

Surtout quand, d’un autre côté, grâce aux Webjars découverts dans Wisdom, gérer des dépendances Javascript dans un projet Maven est d’une simplicité proprement biblique.

Et il y a d’autres bonnes nouvelles …

La première va vous paraître typique du développeur Java fou, mais est en fait plus qu’appréciable dès que le projet grossit un peut (et comme j’ai déja 700 fichiers, on peut dire que c’est déja un gros projet, je pense).

C’est requirejs.

Cette petite librairie, à la documentation rigolote, permet à peu de frais de faire de l’injection de dépendance en Javascript d’une façon qui, sans atteindre la complexité de CDI et de ses scopes/produces/… est quand même vraiment très pratique. Et par très pratique, je veux dire absolument indispensable si on ne veut pas pourir son namespace global avec des tonnes de variables à la noix.

La seconde est un peu une conséquence de la première.

En fait, à l’origine, je voulais suivre le mouton et développer une application AngularJS tout ce qu’il y a de plus traditionnel. Bon, je savais aussi que j’allais avoir vraiment besoin de requirejs. Je ne me voyais donc pas charger une partie de l’application avec requirejs, et en utiliser une autre sans. J’ai donc cherché pendant une journée ou deux comment faire marcher angularJS avec requirejs. Mais aucune des solutions que j’ai vu ne m’a réellement satisfait. Oui, il y a douze réponses sur StackOverflow pointant sur autant de projets nodeJS dans GitHub. Mais

  1. Vous pouvez relire ce que j’ai écrit plus haut sur nodeJS
  2. Même en copiant le code dans mon projet, ça n’a jamais fonctionné de façon convaincante.

Du coup, j’ai du chercher un peu plus.

Et je suis tombé via todoMVC, sur Ractive. Ractive, c’est l’outil de génération d’interface Javascript sympa : il s’insère facilement dans un projet requirejs, il fournit des templates en HTML également chargeables avec requirejs, il veut bien travailler avec jQuery quand il faut, et surtout il est simple à comprendre : pas besoin d’une tripotée de contrôlleurs,factories, et autres idées pénibles issues des plus mauvaises interprétations du MVC (oui oui, je le reproche bien à AngularJS). Non. Il se contente de fournir des contrôleurs, des vues, et des modèles. C’est facile à utiliser, rapide à comprendre, et ça fournit de belles interfaces graphiques.

Bon, en même temps, je sais que l’écosystème Javascript est comme ça depuis ma lecture de Javascript, the world most misunderstood language il y a bien longtemps. Cela dit, j’aime bien l’idée de passer à un langage fonctionnel, sauf lorsque je dois faire (comme c’est le cas aujourd’hui), du code récursif et asynchrone – heureusement qu’il y a les Deferred de jQuery, sinon ce serait authentiquement impossible. En parlant de ça, je ne comprend pas trop le débat sur les Promises/A et les Promises/B. Ca donne l’impression que la communauté Javascript n’a pas de JCP …. oui, je sais, il n’y en a pas, et c’est bien dommage.

J’ai craqué !

Quand je dis ça, je suis un peu mélodramatique … quoique.

Enfin bref.

J’avais déja craqué, pour l’essentiel, en prenant un forfait téléphonique, certes limité (le fameux forfait free 2H/2€). Mais j’étais resté coincé avec un de ces fameux feature phones à clapets et sans applciations, ni gadgets de quelque ordre que ce soit. Un téléphone … pour téléphoner.

Mais là, j’ai craqué d’une autre façon en m’offrant un téléphone Android, avec un grand, beau, (et salissant) écran de 5" qui me rappelle mon Palm d’une autre époque, à un détail près : le Wiko Raimbow que je viens de m’acheter est bien moins cher, et français (enfin, vendu en France par des français, je ne doute pas qu’il soit fabriqué en Chine).

Le moment est donc venu d’apprendre à utiliser un autre OS que Windows ou Mac. Certaines choses sont diablement pratiques, d’autres moins. Mais dans l’ensemble, c’est assez plaisant, je trouve.

Et l’écran, même si il n’est aps reconnu comme exceptionnel, me paraît personnellement être déja une grande victoire.

Par contre, j’ai encore quelques soucis philosophiques de gestion de ma mp3thèque en synchronisation : j’utilisais auparavant iPod manager pour synchroniser mon iPod avec Foobar2000, mais là, je n’y arrive absolument pas. Et ça me paraît bien dommage … Parce que je vais devoir remplacer ça par une copie d’une sélection de mes MP3s préférés dans la carte SD, assortie de l’utilisation d’un podcatcher pour Android. Je ne suis pas très satsifait de ce découpage, mais il faut bien le tester, j’imagine.

 

Le voyage dans le temps, c’est possible sur internet

Notez bien que, dans le sens le plus général, c’est déja possible à travers des outils comme Internet Wayback Machine, mais c’est quand même assez peu pratique.

En revanche, là où ça devient pratique, c’est quand l’historique peut s’afficher directement dans le navigateur. Et ça, c’est ce que propose le protocole Memento. J’imagine qu’il doit y avoir un rapport avec le film, mais lequel … mystère (En passant, la construction en ping-pong marche avant/marche arrière de ce film est la même que celle du superbe roman de Iain M Banks nommé "L’usage des armes").

Enfin bref, memento, c’est une bonne idée.

Mais dans ce cas, pourquoi, POURQUOI, malgré la RFC, choisissent-ils de ne l’implémenter qu’avec Chrome en standard ? Hein ? Pourquoi. Heureusement pour moi, Firefox est open-source, et il existe une extension alternative curieusement nommée mementofox qui va me permettre de tester ce truc que j’imagine dément.

Cela dit, ce dont j’ai vraiment besoin (essentiellement pour le link rewriting dans le lifestream), c’est d’une librairie Java me fournissant l’équivalent de memento, pour pouvoir être sûr de montrer les liens tels qu’ils étaient à l’époque où je les ai sauvegardés. Ca doit pouvoir se trouver, non ? A priori, non, toutefois comme il existe un navigateur memento pour Android, j’imagine qu’il doit être possible d’en extraire le code métier pour faire des requêtes memento à la main …

Ca y est ! J’ai enfin terminé la migration de posterous !

Evidement, ça ne va pas intéresser grand monde … quoique.

Donc, vous vous souvenez de cet article "L’import de posterous, c’est quand même pas ça" ? J’y expliquai rapidement que les caractères non ASCII des articles que j’en importais étaient salement transformés. Au total, j’avais environ 600 articles contenant des accents, et donc contenant des saletés de "??". J’ai donc dû, quasi-manuellement, remplacer tous ces caractères par les vrais bon caractères accentués (merci d’ailleurs aux macros de Notepad++ qui m’ont bien facilité les choses). J’aurais bien aimé, dans l’idéal, pouvoir monter un partage WebDAV pour trouver plus rapidement tous ces articles à mettre à jour. Malheureusement, comme ce blog est hébergé gratuitement par WordPress.com (ce dont je les remercie), je ne peux pas installer de plugins, et je n’ai donc pas accès à mes articles facilement.

D’où cette terriblement longue phase de correction, qui a duré quand même 6 mois !

Du coup, évidement, je suis très content d’en avoir fini avec cet enfer, parce que je peux maintenant passer à des choses plus intéressantes, comme par exemple des améliorations du lifestream.

La première chose à faire, c’est finir d’implémenter le support de WordPress, ce qui me permettra de proposer ce support à l’auteur de JBake …

La deuxième, ce sera sans doute de détecter automatiquement les liens morts. Parce que dans WordPress, comme dans Shaarli, les liens périssent. Et pour l’instant, je ne le détecte pas et c’est bien dommage. Mais je sais que ça viendra !

La liste des plugins que j’utilise avec foobar2000

Parce que je viens de jeter un oeil au site de foobar2000 et que mon retard de version est … très important. Et comme foobar2000 ne gère pas lui-même ses plugions installés (ou alors je suis mal renseigné), je devrais les réinstaller après la mise à jour.

Alors effectivement, j’avais déja fait une liste dans un article subtilement nommé "foobar2000, de plus en plus dingue". Mais je ne suis pas sûr qu’elle soit à jour. Donc allons-y …

Et avec ça, je pourrais faire ma mise à jour rapidement, j’espère.

Allez on reprend proprement …

Bon, suite à la sortie de wisdom 0.6.1, j’ai décidé de reprendre les choses proprement.

Parce que j’ai réfléchi, et j’ai constaté plusieurs erreurs bêtes :

  • J’avais pensé créer un repository Git, mais il ne m’a finalement servi à rien. C’est idiot.
  • D’accord il n’y a pas de tests avec karma, mais je peux utiliser fluentlenium, non ?

Donc cette fois-ci, je vais essayer de faire les choses proprement, avec un repository git bien taggé, avec des tests d’interface, avec les archétypes qui vont bioen, et je vais essayer aussi de parler un peu d’angular.

Donc, reprenons du début …

Pour commencer, je crée le projet facilement puisque Eclipse me permet d’utiliser les archétypes, et que wisdom en propose maintenant un chouette. Donc je mets les bons paramètres, je clique dans le wizard d’Eclipse sur Finish … et c’est parti, j’ai mon application angular-google-shop que vous retrouverez rapidement dans Github (ce point bien précis est dans le tag 01_-_Après_l'appel_de_l'archétype_maven).

Et là, c’est évidement le moment du premier appel à mvn wisdom:run …

Histoire de ne pas reproduire le pataquès précédent, je vais tout de suite me créer un autre contrôleur (un collègue me soufflait d’ailleurs que ce serait bien cool d’avoir des outils de scaffolding comme dans Grails … pas bête).

Donc on y va pour le tutorial angular …. Sans passer par la case Bootstrapping, puisque j’ai déja fait mon projet.

Je la remplace gaillardement par la création d’un autre contrôleur, que j’appelle GoogleShopController, et dont le contenu est à peu près ça

@Controller
public class GoogleShopController extends DefaultController {
}

Maintenant, je vais le remplir … Ce que j’ai déja fait dans Un peu de wisdom, ça fera du bien

Créons donc un template statique  1 – Static Template

Donc, dans mon contrôleur, je crée une View et une méthode pour l’afficher :

    /**
     * Ici "list" est le nom du fichier du template, sans l'extension thl.html
     */
    @View("list")
    Template list;

    /**
     * Et donc quand on va aller sur http://localhost:9000/list, ça va afficher le template {@link #list}
     */
    @Route(method = HttpMethod.GET, uri = "/list")
    public Result todoList() {
        return ok(render(list));
    }

Et le fichier .thl.html qui va bien … Parce que je l’avais pas fait au début, heureusement j’ai eu droit à une belle exception lors de l’affichage, qui m’a poussé à aller voir le monitoring, qui m’a indiqué cette chouette erreur :

Wisdom Monitor __ Controllers_2014-07-08_15-07-00C’est clair, non ?

Bien, j’en suis donc arrivé à la fin de l’étape 1 du tutoriel, et le résultat est dans le tag 01_-_Etape_01_du_tutoriel_Angular_JS_avec_template_statique.

Et voilà les templates  2 – Angular Templates

Rien de bien sorcier là-dedans, mis à part évidement l’ajout des webjars :

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>angularjs</artifactId>
            <version>${angular.version}</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>${bootstrap.version}</version>
        </dependency>

C’est vraiment cool, je l’ai déja dit.

Bien, au passage, j’avais oublié d’ajouter la CSS de Bootstrap.

Et, encore une fois au passage, Wisdom intègre maintenant un chouette gadget pour ne pas trop s’emmerder avec les chemins des assets :

        <link th:href="${#routes.asset('css/bootstrap.css')}" rel="stylesheet"/>

Vous voyez la "fonction" thymeleaf #routes.asset('..') ? Eh bien elle convertit le chemin côté serveur en un chemin utilisable côté client, en s’occupant de toutes ces histoires de transformation de chemin. Bien joué ! D’ailleurs, elle plante joliment sur le chemin que j’ai entré pour angular, preuve que je n’arrive décidément pas à mettre la main dessus …

Ah, ça y est, j’ai trouvé :

        <script th:src="${#routes.asset('angular.js')}"></script>

Dingue, non ?

Tiens, au passage, une petite observation sur Angular …

Dans cette étape, on utilise pour la première fois ng-repeat="...". Un truc me trouble avec ce bidule : j’ai pas l’impression que ce soit du javascript qui y est écrit …je me trompe ? Eh bien non, ng-repeat utilise une "expression". Alors ça c’est bizarre …

Et c’est là qu’arrivent les tests jasmine/karma … pour lesquels je dois écrire un Watcher … A moins bien sûr que je ne décide de faire un test Fluentlenium qui accède à la page HTML de tests Jasmine pour les exécuter … Mouais, je vais plutôt faire ça, tiens …
Bon, j’ai pas été au bout, en revanche, l’approche est tellement bonne que je vais en discuter avec la liste wisdom. En fait c’est assez simple : il faut faire un bout d’application qui déclare un contrôleur JasmineRunner. Ce contrôleur définit une route qui cahrge la page de tests de Jasmine et qui utilise cette page pour produire les résultats des tests. Vous pouvez regardez dans le tag qui va bien 02_-_Etape_02_du_tutoriel_avec_templates_Angular_et_tests_Jasmine.

Filtrons 3 – Filtering Repeaters

Ca va aller vite …

Mis à part que protractor se traduit évidement par un vrai test Fluentlenium :-)

Et là, c’est le drame : je n’arrive pas à trouver la bonne syntaxe pour que ce test marche. En bonus, la syntaxe de Protractor n’a que peu de rapport avec celle de Fluentlenium. Pour tout dire, Protractor me donne l’impression d’un outil très spécifique à Angular, que je trouve de fait d’un intérêt assez faible.

Grmbl ..

Bon, après quelques heures de recherche, il s’est avéré que le test ne marchait pas parce que le driver Selenium par défaut ne supporte pas trop bien la syntaxe Angular.

Et donc, maintenant que j’ai un test Fluentlenium, je peux dire que l’étape 3 est accomplie ! Ce qui donne donc le tag 03_-_Après_l'ajout_du_filtrage.

Trions 4 – Two-way Data Binding

Là aussi, c’est assez rapide puisque je sais déja ce qu’il y a à faire, en fait plus rien de compliqué puisque toute l’infrastructure existe !

En revanche, définitivement, je préfère la syntaxe Fluentlenium. En effet, comme on n’y utilise que le HTML, on "bloque" l’interface dans une forme donnée, sans trop se préoccuper de ce qui est ait au niveau Angular, alors que Protractor fait tout le contraire.

Et du coup, encore un joli tag : 04_-_Après_l'ajout_du_tri.

Bon, comme les étapes suivantes sont du même accabit, je vais accélérer un peu, hein …

5 – XHRs & Dependency Injection

Rien de bien compliqué, juste une copie de fichiers "au bon endroit".

Il y a toutefois un truc malin dans le mock du service HTTP : le fait de flusher à la main la requête permet d’avoir un contrôle très fin sur ce qui se passe. C’est bien vu !

Bon, par contre, ne pas indiquer dans le tutorial que les tests end-to-end peuvent ne plus marcher, c’est pas très sympa … Mais j’ai quand même le tag 05_-_XHR

6 – Templating Links & Images

Bon là il y a un peu de modification de chemins, mais rien de grave … Quelques modifications dans les tests, aussi, mais vraiment rien de grave. Et le tag est 06_-_Liens_et_images.

7 – Routing & Multiple Views

Alors là, je l’ai déja dit, mais globalement, quand ils disent dans le tutorial

The routing functionality added by this step is provided by angular in the ngRoute module, which is distributed separately from the core Angular framework.

Ca veut juste dire d’ajouter le bon script :

<script th:src="${#routes.asset('angular-route.js')}"></script>

Bon il y a aussi un peu de code à modifier, mais rien d’insurmontable … dans le tag 07_-_avec_deux_routes.

8 – More Templating

Dans le tag 08_-_avec_un_beau_template_pour_les_détails. Je dois juste à l’honnêteté de dire que j’ai réutilisé le test d el’étape 7, parce qu’il y avait franchement une répétition.

9 – Filters

Ca donne un joli tag de plus 09_-_avec_des_filtres_de_rendu … Et l’envie certaine d’intégrer les tests Jasmine dans le build.

10 – Event Handlers

Trop facile ! Y compris le test Fluentlenium qui va bien. D’où le tag 10_-_avec_des_événements.

11 – REST and Custom Services

Là, comme pour les routes, il faut ajouter un module dans bower, c’est-à-dire que c’est déja fait avec webjars … Bon, le mauvais point de mon runner Jasmine actuel, je dois le dire, c’est qu’il n’arrive pas à récupérer les scripts utilisés dans list.thl.html, et c’est dommage. Mais j’imagine qu’un peu de lecture de thymeleaf m’y aiderait …

Ah, petite blague : Angular a écrit son tutorial avec Jasmine 1.3, et ne l’a pas mis à jour. Mais jasmine 2.0 change le style d’écriture des custom matchers, d’où un beforeEach un peu différent de la version fournie avec angular (que je n’ai par ailleurs aps réussi à faire marcher de façon satisfaisante).

J’en ai aussi profité pour m’assurer que je compilais bien en 1.7 …

Et j’ai donc créé le tag 11_-_avec_un_service_REST.

12 – Applying Animations

Bon, il y a le traditionnel ajout d’un module angular …

 <script th:src="${#routes.asset('angular-animate.js')}"></script>

Et l’ajout de …jQuery ? WTF ?!#
Ah, au fait, notez bien qu’à cause d’un "bug" Wisdom, si vous ajoutez un webjar, il faut relancer wisdom:run à la main pour l’instant … Bref …

Revenons-en à nos animations. C’est pas compliqué compliqué, je trouve juste bizarre d’avoir une animation jQuery alors que le tutorial dit bien

jQuery isn’t required to do JavaScript animations with AngularJS, but we’re going to use it because writing your own JavaScript animation library is beyond the scope of this tutorial

Est-ce que c’est pas une façon déguisée de dire que les animations avec jQuery sont quand même plus simples qu’avec angular ?

Cela dit, j’ai mon tag 12_-_avec_des_animations. Et j’ai fini le tutorial !

Conclusion

J’espère vous avoir convaincu, malgré le côté un peu expérimental de cette histoire, de l’intérêt d’utiliser wisdom. Pourquoi ?

  • Parce que le packaging javascript utilisant les webjars est bien plus simple
  • Parce que les tests Fluentlenium sont eux aussi bien plus simples à écrire que les tests protractor
  • Parce que je n’ai pas parlé des optimisations des images, de l’utilisation de LESS, de Typescript, ou d’autres fonctionnalités encore plus chouettes
  • Et enfin parce que lorsqu’on package une application wisdom, on package un tout : client et serveur, bénéficiant à la fois de la facilité de Javascript, et de l’écosystèpme serveur Java.

La suite ?

Je pourrais, dans une version ultérieure, faire un peu de code serveur : générer le phones.json à aprtir d’une servlet quelconque, gérer la sécurité, faire du push via websockets, … Mais pour ça, on verra plus tard.

 

Encore un peu de wisdom ?

Ben oui, après le message de la semaine dernière, vous ne vous attendiez tout de même pas à ce que ça s’arrête aussi vite ! Surtout que l’équipe de wisdom a sorti une version 0.6 (ce serait d’ailleurs bien d’avoir une page différente par release, parce que là, c’est pas super pratique), que je me suis empressé d’installer, et qui fournit un monitor que je trouve très bien (surtout parce qu’il liste les routes utilisables).

Donc, j’ai mis à jour, j’ai lancé mon application, toujours sur les traces du tutorial angular, et je suis passé à la page où on ajoute du javascript. Et j’ai remarqué plusieurs choses …

D’abord, évidement, que je pouvais appeler angular avec la bonne déclaration HTML :

<script src="/libs/angular.js"/>

Ensuite, et ça n’est pas évident pour moi, les tests Java ne sont pas relancés quand on redéploie l’application. J’ai bien l’impression que si l’équipe de wisdom regardait ce que fait par exemple Infinitest (je dis infinitest, mais je crois qu’il y a au moins un autre outil de test du même style. Sinon, reflections doit être capable de trouver les références à une classe Java dans tout un projet, je pense), ils pourraient facilement exécuter les tests "intéressants" au redéploiement.

Dans le même ordre d’idées, je sais bien que wisdom encapsule une instance node. Donc, quand angular me dit de faire un test Javascript, j’imagine que je dois pouvoir le faire quelque part … mais où ? La doc de wisdom ne me semble pas indiquer ça. Tiens, et ils annoncent en bonus

Angular developers prefer the syntax of Jasmine’s Behavior-driven Development (BDD) framework when writing tests. Although Angular does not require you to use Jasmine, we wrote all of the tests in this tutorial in Jasmine v1.3. You can learn about Jasmine on the Jasmine home page and at the Jasmine docs.

The angular-seed project is pre-configured to run unit tests using Karma but you will need to ensure that Karma and its necessary plugins are installed. You can do this by running npm install.

OK, mais moi, dans mon projet, je n’ai pas de dépendance qui s’appelle karma ou Jasmine. j’imagine donc qu’il s’agit plus ou moins d’une forme de webjar … Ah, oui, jasmine est un webjar. Mais karma ? D’après la doc, il semble que je doive développer une extension de watcher (ou tout au moins un mojo) pour pouvoir l’utilser … C’est pas un peu beaucoup, là ?

J’imagine que je vais pouvoir commencer une FAQ officieuse pour wisdom avec toutes les réponses que je glane en les tanant par mail :-)

Bon, c’est assez de frustration pour aujourd’hui, je crois :-) Ce qu’il faut toutefois comprendre, c’est qu’il s’agit de frustrations somme toute mineures : je pourrais tout à fait faire une application pure Java, avec des pages HTML statiques. Là, je me complique un peu la vie parce que je creuse les détails de l’intégration client/serveur. Et je suis quand même franchement admiratif du boulot fourni sur Wisdom. J’imagine que je peux dire "à la semaine prochaine pour un autre épisode".

Mojo Executor

Admettons que vous deviez écrire un Mojo maven. ou, pire encore, un cycle de vie personnalisé. Vous allez sans doute faire des trucs déja implémentés par d’autres plugins maven. Et vous vous en voudrez.

Eh bien pour que vous ne vous en vouliez plus, n’éhsitez pas à appeler ces cibles directement avec Mojo-Executor.

Allez voir sur le site, c’est vraiment très très pratique dès qu’on veut reprendre un truc déja disponible dans un plugin du build. Et par vraiment, j’euphémise à mort. En fait, ça change tout.

Bon, il y a juste un truc qui me chiffone un peu, c’est qu’il faut lui passer un Plugin complet (c’est-à-dire avec une version valide). or, dans le code java, la version, on ne la connaît pas forcément, d’autant plus que le projet peut déja utiliser ce plugin et que, dans ce cas-là, sa version est déja connue des composants Maven. D’où cette petite méthode qui facilite bien la vie :

Ah, et si ça ne suffit pas, ajoutez-y ces petites méthodes qui facilitent l’ajout d’attributs (très pratique quand on fait de l’ant-exec)

Avec tout ça, votre prochain mojo sera vraiment facile à écrire.

Au passage, il semble que le même type ait écrit un maven-cli-plugin, actuellement difficile à trouver, pour éviter la perte de temps du démarrage de maven (ce qui ne m’intéresse pas professionnellement, puisque notre build prend 20 mns à s’exécuter).

Un peu de wisdom, ça fera du bien

Bon, cet après-midi, j’ai un peu de temps, donc je vais vous live-blogger une expérimentation.

L’expérimentation,, en l’occurence, est l’utilisation de wisdom-framework pour créer l’exemple canonique d’AngularJS : une liste de tâches mises à jour de façon "moderne". L’objectif est d’arriver avant la find e la journée à une application web qui enregistre les TODOs dans un fichier au format todo.txt.

EDIT : cet objectif n’a pas été atteint, parce que j’ai perdu un peu de temps sur l’install, et surtout parce que le fameux exemple de todo avec angular ne semble pas exister … bizarre.

Ah, mais vous ne connaissez pas wisdom ? C’est normal, c’est assez jeune, mais pourtant porteur d’innombrables promesses (et j’exagère à peine en disant ça). C’est donc un framework pour applications web basé sur la modularité et le dynamisme.

La modularité, grâce à OSGi, permet de découper une application web en paquets de tout petits blocs faciles à modifier, faciles à faire évoluer à peu près indépendament, mais pourtant utilisant des ressources communes.

Le dynamisme permet, encore grâce à OSGi, mais aussi grâce à maven, de développer aussi vite qu’avec une application pure Javascript, tout en bénéficiant de l’écosystème et des capacités de typage de Java. Enfin bon, vous allez voir avec moi.

Créer le projet

Facile, c’est documenté (la doc de wisdom me paraît d’ailleurs dans l’ensemble fort bien fichue – de toute façon, il suffit d’aller sur GitHub ou dans le Google Group pour poser des questions …). Donc allons-y :

mvn org.wisdom-framework:wisdom-maven-plugin:0.5.1:create -DgroupId=fr.fot.java.wisdom -DartifactId=wisdomTodo -Dversion=0.0.1-SNAPSHOT

Et normalement, c’est bon … sauf qu’entre ma version de maven incorrecte (3.0.4), mon Java incorrect (1.6.0_40), ça ne marche pas en ligne de commande et, de la même manière, créer le projet à partir de l’archétype dans Eclipse échoue lamentablement avec un message … cryptique :

Unable to create project from archetype [org.wisdom-framework:wisdom-maven-plugin:0.5.1 -> ]
The desired archetype does not exist (org.wisdom-framework:wisdom-maven-plugin:0.5.1)

Ca fait bizarre … Bon, je crée le projet à la main et je reviens …

Et pour créer le projet à la main, histoire que vous ne perdiez pas autant de temps que moi, si vous êtes dans Eclipse, la commande d’au-dessus se traduit sous la forme

Run Configurations_2014-06-20_16-03-09

A lancer dans un "Base directory" vide pour que ça se passe bien.

Et donc, une fois que c’est fait, je tape mvn wisdom:run, je vais sur http://localhost:9000 (ne craignez rien, ces instructions sont, encore une fois, indiquées dans la doc), et j’ai droit à une très jolie page m’indiquant que faire après …

Une page fournie par le WelcomeController. Le meilleur étant évidement que, quand je renomme le package de ce contrpoleur, je vois la console wisdom s’agiter un moment, puisque l’application est rechargée dans le dos d’Eclipse (c’est bon ça Clément !).

Ajouter une route à l’application

Donc maintenant, pour ajouter une nouvelle page (oui, je vais ajouter ma page avant de remplacer la @Route par défaut dans le contrôleur), ça me paraît assez facile :

    /**
     * Ici todo est le nom du fichier du template, sans l'extension thl.html
     */
    @View("todo")
    Template todoList;

    /**
     * Et donc quand on va aller sur http://localhost:9000/list, ça va afficher le template #todoList qui n'existe pas encore ... d'où une erreur.
     * @return
     */
    @Route(method = HttpMethod.GET, uri = "/list")
    public Result todoList() {
    	return ok(render(todoList));
    }

Et quand j’essaye de taper http://localhost:9000/list dans mon navigateur j’ai droit … évidement à une belle page d’erreur, puisque le tempalte n’existe pas ! Donc je le crée avec un contenu … quelconque.

Et devinez quoi ? Eh bien évidement, ça marche !

Bon, je n’ai plus qu’à rempalcer ce contenu par celui de l’exemple d’Angular JS  … qui a malheureusement été remplacé par exemple commercial. Pas grave, on peut le trouver ailleurs (la deuxième version est bien plus simple pour un noob comme moi).

Et là c’est le drame : les attributs ng-app d’Angular viennent foutre le bazar dans le parsing XML :

Caused by: org.thymeleaf.exceptions.TemplateInputException: Exception parsing document: template="bundle://58.11:0/templates/todo.thl.html", line 13 - column 13
	at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.parseTemplateUsingPool(AbstractNonValidatingSAXTemplateParser.java:167) ~[na:na]
	at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.parseTemplate(AbstractNonValidatingSAXTemplateParser.java:117) ~[na:na]
	at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:277) ~[na:na]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1104) ~[na:na]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060) ~[na:na]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011) ~[na:na]
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:955) ~[na:na]
	at org.wisdom.template.thymeleaf.impl.WisdomTemplateEngine.process(WisdomTemplateEngine.java:85) ~[na:na]
	at org.wisdom.template.thymeleaf.impl.ThymeLeafTemplateImplementation.render(ThymeLeafTemplateImplementation.java:120) ~[na:na]
	at org.wisdom.api.templates.Template$$Proxy.render(Unknown Source) ~[na:na]
	at org.wisdom.api.DefaultController.render(DefaultController.java:188) ~[wisdom-api-0.5.1.jar:na]
	at fr.fot.java.wisdom.todo.WelcomeController.__M_todoList(WelcomeController.java:65) ~[na:na]
	at fr.fot.java.wisdom.todo.WelcomeController.todoList(WelcomeController.java) ~[na:na]
	... 33 common frames omitted
Caused by: org.xml.sax.SAXParseException: Le nom d'attribut "ng-app" associ� � un type d'�l�ment "html" doit �tre suivi du caract�re '='.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:441) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1375) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanAttribute(XMLDocumentFragmentScannerImpl.java:1489) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1279) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2715) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568) ~[na:1.7.0]
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:302) ~[na:1.7.0]
	at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.doParse(AbstractNonValidatingSAXTemplateParser.java:210) ~[na:na]
	at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.parseTemplateUsingPool(AbstractNonValidatingSAXTemplateParser.java:134) ~[na:na]
	... 45 common frames omitted

En même temps, je sais que c’est ça essentiellement grâce à une très bonne remontée d’erreur (c’est un avantage certain). Du coup je replonge dans la doc de wisdom pour voir comment angular et thymeleaf peuvent vivre ensemble … Ah en fait ça n’est pas dans la doc de Wisdom, mais sur la ML de Thymeleaf.

Bon, et du coup, une fois que j’ai modifié l’entête pour

<!doctype html>
<html data-ng-app="">

que j’ai fermé les différents tags mal fermés et corrigé deux ou trois boulettes, ma page s’affiche … mochement, je dois dire :-)

Je peux donc y ajouter le contrôleur pour angular, que je copie-colle également sans m’embêter. Mais avant ça, je vais d’abord ajouter les webjars demandés (quelle chouette idée, ces dépendances javascript utilisables facilement) …

Mais ça, ce sera pour une autre fois.

Parce que les mecs d’angular semblent avoir décidé de changer leur exemple (que j’ai pourtant vu des dizaines de fois) et que, n’ayant plus de tutoriel parfaitement clair, je ne peux même plus tenter d’adapter ce que je vois à ce que wisdom me fournit (parce que figurez-vous que je ne connais malheureusement pas encore l’outil).

Bon, bref. J’y reviendrai sans doute la semaine prochaine. En tout cas, je suis plutôt séduit par la facilité avec laquelle wisdom s’installe, s’adapte, et se met à jour quand on change du code.

Comme quoi l’apprentissage n’est pas toujours un chemin facile. Surtout quand on se met soi-même des bâtons dans les roues.