Archives de Catégorie: Uncategorized

This blog has moved

It’s now at hypedrivendev.io

See you there!

Développer pour Google Glass

Vous n’êtes probablement pas passés à côté de l’existence des Google Glass et vous êtes même probablement intrigués et impatients d’en essayer. Peut être aussi un peu effrayés par ces nouvelles caméras qui vont nous observer dans la vie de tous les jours. Moi aussi. Mais on imagine aussi les possibilités que peuvent offrir un tel device : cela fait donc un moment déjà que je voulais voir comment développer pour Google Glass.

Il existe deux façons de procéder :

– utiliser une API REST (nommée Mirror API) pour envoyer des « cartes » (ce qui s’affichera en haut à droite de l’oeil de votre utilisateur) aux Glasses, pour les insérer dans une Timeline.
– développer une application embarquée sur le device, grâce au Glass Development Toolkit. Cette option a l’avantage de vous donner accès au hardware et de faire du offline. Le Development Kit est assez proche de celui qui permet de faire des applications Android.

L’idée

Mon idée était relativement simple : avec Mix-IT qui approche (disclaimer : je fais parti de l’orga), pourquoi ne pas faire le programme de la conf sur Glass ? Le site de Mix-IT expose déjà une API pour récupérer les différentes sessions, il suffisait donc de trouver le moyen d’envoyer une notification à l’utilisateur avant chaque session. Cela ressemblait bien à ce que proposait la Mirror API !

L’API propose même d’envoyer des « bundles » de cartes : c’est à dire un groupe de cartes, avec une carte particulière pour la couverture. L’idée était donc d’envoyer un bundle de carte quelques minutes avant le début d’un créneau horaire, avec :

– une carte de couverture qui résume le nombre de talks et de workshops à venir, ainsi que l’heure.
– une carte dans le bundle pour chaque talk et workshop, avec le nom de la salle, le titre et la photo du speaker.

La stack

Pour la partie technique, ce qui est cool avec la Mirror API, c’est que vous êtes libres de choisir votre langage préféré pour appeler l’API REST. Google fournit même des librairies facilitant l’utilisation de l’API dans différents langages.

Bonne occasion pour faire un peu de Java 8!

Il est également nécessaire de demander l’autorisation à l’utilisateur d’accéder à sa timeline, il faut donc avoir une page Web très simple qui permet à l’utilisateur de déclencher l’autorisation OAuth, puis à notre code de récupérer le token généré.

Un serveur Web très léger en Java 8 ? Bonne occasion pour essayer fluent-http de la team CodeStory !

Enfin, pour le déploiement, mon obsession du moment s’appelle [Docker](http://docker.io). J’espérais donc pouvoir déployer l’application sur Google Compute Engine, qui propose de faire ça depuis peu.

La réalisation

D’abord, commençons par déclarer notre application Glass. Il suffit de se rendre dans la console Google et de créer un projet, en activant l’API Google Glass dans la partie API puis en enregistrant les URLs autorisées qui vous intéressent (serveur de dév et de prod) dans les credentials. Il faut en effet indiquer à Google quelle URL de callback il devra appeler une fois l’authentification réussie (et
c’est ainsi que l’on récuperera notre token).

Première étape de dév, afficher une petite page statique grâce à fluent-http. Super simple, ce que vous mettez dans le dossier `app` de votre projet est automatiquement servi! Le serveur supporte même différents formats (markdown, yml…).

Application.java

    new WebServer(routes -> {
      routes.get("/", Model.of("oauth", oAuthUrl)
    }).start(8081);

index.html

    <h1>Mix-IT, now on Google Glass</h1>
    <a href='[[oauth]]'>Try it!</a>

Le serveur va répondre le fichier `index.html` et remplacer la variable `oauth` par celle définie dans le code, qui contient l’url d’authentification à appeler.

Ensuite, il faut récupérer le token renvoyé par OAuth. Google met à disposition une librairie utilitaire pour faire la majeure partie du travail, mais, soyons honnête, elle est assez désagréable à utiliser (mal pensée, mal codée, mal documentée). Elle permet quand même de faire l’essentiel du travail sans trop se fatiguer.

On définit donc une nouvelle route dans notre serveur pour récupérer le token renvoyé sur l’url de callback `/subscribe?code=monToken`.

    routes
    .get("/", Model.of("oauth", oAuthUrl)
    .get("/subscribe", context -> {
      storeCredentials(context.get("code"));
      return ModelAndView.of("success");
    })

Le token est stocké, et les prochaines notifications peuvent donc être envoyées à l’utilisateur.

Il ne reste plus qu’à récupérer le programme et envoyer au bon moment les cartes aux utilisateurs inscrits. Pour cela, on récupère le JSON du programme exposé par le site et on le parse. Quitte à être en Java 8, autant utiliser les nouveaux types Date du jdk8 : pour cela Jackson propose un module de sérialisation/déserialisation tout prêt.

C’est plaisant de faire du Java 8, par exemple regrouper les talks par leur heure de début se fait en une ligne :

    talks.stream().collect(groupingBy(Talk::getStart));

`groupingBy` est une méthode offerte par la classe Collectors, et fait le travail pour nous.

ou encore les ordonner, et récupérer le prochain talk :

    talks.keySet()
      .stream()
      .min(Comparator.naturalOrder())
      .get();

C’est simple, ca se lit bien, c’est efficace.

Il n’y a plus qu’à construire le bundle de cartes. Construire une carte est très facile, la librairie Google possède une classe `TimelineItem` avec un attribut `html` dans lequel vous mettez ce que vous voulez afficher à votre utilisateur.

Pour simplifier, voilà comment est construite une carte :

    <article>
      <section>
        <div class="layout-figure">
          <div class="align-center">
            <p class="text-x-large">talk.getStart()</p>
            <p class="text-normal">talk.getRoom()&lt;/p
          </div>
          <div class="text-large" style="background-image:url('talk.getSpeakers().get(0).getUrlimage()');">
            <p>talk.getTitle()</p>
          </div>
        </div>
      </section>
    </article>

Vous pouvez constater qu’il y a quelques classes CSS disponibles pour la taille des textes,
ou leur couleur par exemple.

Une fois les cartes construites, on les envoie aux utilisateurs :

    credentials.forEach(credential -> getMirror(credential).timeline().insert(item).execute());

Yay! \o/

Le déploiement

Donc en ce moment j’aime bien Docker. Et les articles de David Gageot m’avaient donné envie de tester Google Compute Engine. C’est parti pour faire l’image Docker de l’application!
On prépare un Dockerfile qui installe Java 8, on lui ajoute les sources du projet, on expose le port de la webapp et on la démarre. Ca a l’air facile? Ca l’est!

Dockerfile

    from base
    maintainer Cédric Exbrayat

    # Install prerequisites
    run apt-get update
    run apt-get install -y software-properties-common

    # Install java8
    run add-apt-repository -y ppa:webupd8team/java
    run apt-get update
    run echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
    run apt-get install -y --force-yes oracle-java8-installer

    # Install tools
    run apt-get install -y maven

    # Add sources
    add ./ ./glass
    workdir ./glass

    # Build project
    run mvn install -DskipTests

    # Expose the http port
    expose 8081

    # Launch server on start
    cmd mvn exec:java

Y’a plus qu’à déployer! Mais en fait Google Compute Engine est payant, même pas un petit mode gratuit comme App Engine. Pas grave, on a déjà un petit serveur avec Docker installé, ca fonctionne pareil! Je rajoute un petit script chargé de tuer le container démarré, et de lancer la nouvelle version :

run.sh

    # Kill old container
    echo "kill old container"
    alias docker="docker -H 0.0.0.0:4243"
    docker kill $(cat docker.pid)

    # Build new image
    echo "build image"
    docker build -t ninjasquad/mix-it-on-glass .

    # Run image
    echo "run image"
    DOCKER_CONTAINER=$(docker run -p 8081:8081 -d ninjasquad/mix-it-on-glass)

    # Save container id
    rm docker.pid
    echo "$DOCKER_CONTAINER" >> docker.pid

Procédure de déploiement : `git pull & ./run.sh`.
Temps de déploiement : 15 secondes (quasi entièrement dévolue au build Maven pendant la construction de l’image).

Le test

Vous allez me dire : « Mais t’as des Google Glass toi ? ». Non, j’en ai pas. Alors, comment je fais pour tester ? Google propose un Playground pour visualiser sa timeline Glass. Bizarrement assez buggué (les cartes n’apparaissent pas parfois), cela permet quand même de voir si les cartes
sont correctement insérées dans la timeline (même si il faut rafraîchir manuellement, alors que l’on pourrait s’attendre à quelque chose de plus… temps réel!) et d’éditer leur contenu pour jouer avec.

Vous pouvez essayer vous même! C’est par ici : mix-it-on-glass.ninja-squad.com.

TL;DR;

Le développement pour Glass est assez simple, surtout du HTML pour faire de belles cartes, et le langage que vous préférez pour insérer ces cartes dans la timeline. La partie OAuth est légérement simplifiée en utilisant une librairie proposée par Google, même si celle-ci n’est pas fantastique en Java…

Bon, maintenant j’attends de voir des Glass pour faire un test de mon programme. Si vous en avez, tenez moi au courant !

JHipster – boost your Spring and AngularJS app

Mon blog s’appelant Hype Driven Development, ça me semblait difficile
de ne pas faire un article sur JHipster, le générateur d’application full stack pour
les hipsters du Java (avouez, c’est difficile de résister).

Un générateur? Oui, un générateur Yeoman. Vous avez peut être entendu parler
de cet outil, fort pratique pour générer des squelettes de projets,
par exemple pour commencer votre prochain projet Angular (c’est d’ailleur le générateur le plus connu).
Yeoman fournit le moteur de base, et vous pouvez installer les générateurs qui vous intéressent.
Il y en a plein et JHipster commence à être fort populaire.

JHipster est un générateur d’application Spring/AngularJS, et donne un projet tout bien
configuré et prêt à démarrer en moins de 10 minutes,
qui se répartissent entre taper 2 commandes et répondre à quelques questions (2 minutes),
regarder NPM télécharger la partie paire de l’internet (3 minutes) et Maven télécharger la partie impaire (5 minutes).
Oui c’était jour de circulation alternée.
Les seuls pré-requis sont donc NodeJS et NPM, un JDK 1.7 et Maven 3.

Stack serveur

Alors qu’est-ce que ça nous a installé ?
Côté serveur, cela s’appuie sur Spring Boot, un projet assez récent
qui permet de créer rapidement une application fonctionnelle avec Spring 4.
C’est clairement un projet que les équipes Spring veulent mettre en avant, pour montrer
que la création d’une application Spring peut être très simple. Spring Boot va créer une application toute prête
(une CLI est disponible, ou un plugin pour votre outil de build préféré), un pom.xml configuré, un serveur Tomcat ou Jetty embarqué,
pas de XML ou de code généré. Vous avez une classe de démarrage de votre application
avec quelques annotations dessus, et ça roule. Spring Boot ramène des copains à la fête :
Spring MVC pour les controllers REST.
Jackson pour la sérialisation JSON.
Spring JPA et Hibernate pour la partie accès aux données.
HikariCP pour le pool de connexion JDBC.
Spring Security pour la gestion des utilisateurs et de l’authentification.
Joda Time pour la gestion des dates (ca devrait être inutile en Java 8).
Metrics un framework de monitoring, développé par Yammer.
Thymeleaf si vous voulez faire des templates côté serveur.
– les drivers de la base de données choisie (H2, PG ou MySQL).
Liquibase pour gérer les changements de schéma (très pratique comme outil).
JavaMail pour les… mails.
EhCache ou Hazelcast selon le cache choisi.
Logback pour la gestion des logs.
JUnit, Mockito et
Awaitility pour les tests.

Pas mal de code est déjà généré également, notamment pour la partie sécurité,
avec une classe utilisateur, une pour les rôles, une autre pour les audits…
Et bien sûr les repositories, services et controllers associés.
Un service d’authentification est déjà prévu avec une configuration très solide.
L’organisation des sources est claire et très classique, on s’y retrouve facilement.
Les ressources contiennent le nécessaire pour la configuration Liquibase, les fichiers
YAML de paramétrage de Spring selon le profil (deux profils, prod et dev sont fournis).
C’est dans ces fichiers que vous pourriez configurer votre BDD ou votre serveur mail par exemple.
On trouve également les fichiers de messages pour l’i18n, dans plusieurs langues.
Enfin, figurent aussi les fichiers de config du cache et du logger.

Dans les tests, on trouve des exemples de tests unitaires et de tests de controllers REST.

Stack client

Passons côté client. On a bien sûr du AngularJS (what else?).
Grunt est l’outil de build choisi (pas encore de Gulp? c’est pourtant plus hype…), il est déjà bien configuré
pour surveiller les fichiers et les recharger à chaud au moindre changement sauvegardé, passer JsHint pour vérifier,
tout minifier et concaténer. Bower est là pour la gestion de dépendances, rien d’exotique dans ce qui est récupéré :
Angular et ses différents modules indispensables (routes, cookies, translate…). On retrouve bien sûr Twitter Boostrap
pour faire joli et responsive. Les tests unitaires (avec quelques exemples fournis) sont lancés grâce à Karma,
pas de tests end-to-end en revanche.

Le fichier `index.html` est basé sur HTML5 Boilerplate, les fichiers CSS et i18n sont là.
Les scripts JS sont regroupés par type (`controllers.js`, `services.js` …).
Les déclarations d’injection Angular sont faites en mode tableau de chaîne de caractères pour éviter les problèmes de minification.
C’est un bon point, le générateur Yeoman pour Angular propose d’utiliser le plugin ngmin, mais celui-ci a quelques limites.
La sécurité est aussi gérée côté client. Enfin un certain nombre de vues sont disponibles d’origine pour le login et des vues
d’administration : gestion des logs, des perfs.

Run

Lançons tout ça!
Le projet démarre sur le port 8080 avec un simple `mvn spring-boot:run`, sur un écran d’accueil. On peut se connecter en tant qu’admin
et voir des écrans de gestion de profil (mot de passe, settings, sessions), l’écran d’audit (avec la liste des événements), l’écran de configuration des (977!!) loggers par défaut,
dont on peut changer le niveau à chaud, et enfin l’écran exposé par Metrics, avec les différentes… métriques donc!
On peut y voir des ‘Health checks’ (est-ce que la base de données est up? le serveur de mail?), les stats de la JVM
(mémoire, threads, GC), les requêtes HTTP, les statistiques des différents services (nombres d’appel, temps moyen, min, max et différents percentiles)
et enfin les statistiques du cache. J’aime beaucoup cette intégration d’un outil de monitoring simple, c’est certainement
quelque chose que j’utiliserai sur mes projets.
Il est possible de changer dynamiquement le langage de l’application (merci angular-translate).

Développement

JHipster permet aussi de générer des entités pour nous,
depuis la base de données jusqu’à la vue Angular, en passant par le repository et le controller Spring,
la route, le service et le controller Angular. C’est un peu anecdotique (la génération de code, à force…), mais ça marche, et ça
donne un CRUD tout à fait utilisable pour des écrans d’admin. Le service Spring doit lui être généré à part, pour
ne pas encourager la production de code inutile (ce qui est un peu paradoxal pour un générateur de code, vous en conviendrez, mais
je suis sensible au geste).

Ce qui est plus impressionnant, c’est que le projet utilise Spring Loaded, que j’ai découvert très récemment
(merci Brian de l’équipe Spring au détour d’un café à la Cordée!), et que cet agent permet le rechargement de code à chaud, même
lors d’un ajout de bean Spring! Couplez ça à Grunt et son LiveReload, et chaque modification est prise en compte
instantanément. Très très cool! Je pense que Spring Loaded va se retrouver sur les projets Ninja Squad d’ici peu.

Il faut quand même reconnaître qu’entrer la commande

yo jhipster:entity campaign

Puis se rendre directement dans son navigateur à l’url ‘/campaign’ et avoir le CRUD fonctionnel devant les yeux
en moins d’une seconde alors que cela a créé des tables en base, des beans Springs, du JS, qu’on a rien relancé,
c’est quand même pas mal la classe internationale.

TL, DR;

La stack complète est au final extrêmement proche de celle que nous utilisons
sur certains projets chez Ninja Squad : Spring MVC, Spring JPA, Spring Data,
HikariCP, Liquibase, Bower, Grunt, NPM, AngularJS, à l’exception donc
de Spring Boot, Spring Loaded, Metrics, Spring Security et nous préférons LESS à Compass et FestAssert pour les tests.
Puis on fait du Gradle, parce que certains n’aiment pas Maven (je ne donnerai pas de noms).

Mais je crois que Spring Loaded et Metrics vont bientôt rejoindre mes outils favoris.

JHipster propose aussi de faire des WebSockets avec Atmosphere ou
de gérer le clustering des sessions HTTP avec Hazelcast.

Bref, plein de bonnes idées, même si vous connaissez bien toutes les technos, et de bonnes pistes de configuration
si vous les découvrez.

Si vous ne saviez pas comment démarrer votre prochain projet Web Java, vous savez maintenant par quoi commencer!
En plus JHipster propose un container Docker pour tester. Si ça c’est pas le top
de la hype 2014, je sais plus quoi faire…

Workflow, Pull Requests & Code Reviews

Si vous suivez le blog de Ninja Squad, vous savez que nous avons déjà parlé du workflow Git que nous utilisons en local. Mais on ne vous a jamais expliqué les différentes façons de collaborer à plusieurs sur un projet.

Il y a deux grandes façons de travailler à plusieurs :
– un repo partagé par toute l’équipe
– un repo pour chaque développeur

Workflow & Pull Requests

Open Source style

Cette dernière façon est la plus répandue dans le monde open source. Admettons que vous vouliez contribuer au projet AngularJS. Vous n’avez pas les droits d’écriture sur le repository Github utilisé par le projet tant que quelqu’un de l’équipe ne vous les donne pas. Ce qui semble assez logique vu qu’ils ne vous connaissent pas 🙂

Donc, si vous voulez contribuer au projet, il faut commencer par faire un fork. Il y a un gros bouton sur Github qui permet de faire ça et qui va copier le projet AngularJS dans votre espace utilisateur (par exemple `cexbrayat/angular.js`). Sur ce nouveau repository, j’ai les droits d’écriture. Je peux donc le cloner sur mon laptop :

git clone https://github.com/cexbrayat/angular.js

Une fois cloné, le repository Github est référencé comme le repo ‘origin’ dans nos remotes. Je peux faire des modifications dans une branche :

cd angular.js
git branch awesome-feature
git checkout awesome-feature
... commits

et pousser mon code sur mon repository :

git push origin awesome-feature

Il faut noter que ce repository n’est pas synchronisé automatiquement avec le repository forké : si les développeurs de la team Google ajoutent de nouveaux commits au repository `angular/angular.js`, nous ne les verrons pas dans notre repository. Si ces commits nous intéressent, il est possible d’ajouter ce repo come un autre de nos remotes. Par convention, ce repository est généralement appelé ‘upstream’.

git remote add upstream https://github.com/angular/angularjs

On peu coder notre fonctionnalité comme précédemment :

git branch awesome-feature
git checkout awesome-feature
... commits

Et l’on peut maintenant récupérer les modifications de la team Google et mettre à jour notre branche locale avec celles-ci :

# on récupère les derniers commits de upstream
git fetch upstream
git rebase upstream/master
# on pousse notre branche à jour
git push origin awesome-feature

Une nouvelle branche `updated-with-upstream` sera alors ajoutée sur notre repository Github, à jour avec les dernières modifications faites par l’équipe de Google.

Si cette branche contient une fonctionnalité que vous voulez contribuer, vous pouvez alors créer une pull request. En vous plaçant sur votre branche dans l’interface Github, vous pouvez choisir de créer une pull request vers le repository que vous avez forké, par défaut sur la branche `master`, mais rien ne vous empêche de changer de branche. Vous entrez alors un titre, une description du but de cette PR. Lorsque vous validez, les propriétaires du repository sur lequel vous avez fait la PR vont recevoir un mail leur indiquant l’arrivée d’une nouvelle requête.

Dans l’interface Github, ils pourront faire une revue de code, mettre des commentaires sur certaines lignes (vous ne vous attendiez pas à réussir du premier coup si?), puis enfin choisir de refuser la PR (dommage) ou de la merger (\o/). Dans ce dernier cas, votre code sera ajouté à la branche en question, bravo!

Github fournit maintenant un ensemble de guides fort pratiques pour débuter : vous pouvez regarder celui sur le workflow des PRs.

Enterprise style

En entreprise, le workflow est généralement différent. La plupart du temps, l’équipe collabore sur un seul repository sur lequel tout le monde possède les droits d’écriture. Il y a donc deux façons de procéder.

La première consiste à pousser ses modifications directement sur le `master` (si c’est votre branche de développement actif). On laisse alors le soin à l’intégration continue de repérer tout problème (il n’y a plus qu’à espérer avoir suffisamment de tests…).

git branch feature-one
git checkout feature-one
... commits
# on récupère les derniers commits de origin
git fetch origin
git rebase origin/master
# on pousse notre branche à jour sur le master
git push origin feature-one:master

La seconde consiste à pousser ses modifications sur une branche partagée, puis de créer une pull request entre cette branche et le master! L’avantage est de pouvoir faire une revue de code sur cette pull request, d’en discuter puis de l’intégrer.

git branch feature-one
git checkout feature-one
... commits
# on récupère les derniers commits de origin
git fetch origin
git rebase origin/master
# on pousse notre branche à jour sur une branche partagée pour faire une PR
git push origin feature-one

Code review, sweet code review

Le mécanisme de code review est vraiment intéressant à systématiser. Bien sûr, cela introduit une tâche supplémentaire, que l’on peut voir comme une perte de temps. Mais il est très difficile de coder juste tout le temps du premier coup (en tout cas moi je sais pas faire), et un oeil externe peut souvent voir certains problèmes qui nous ont échappé au moment de la réalisation.

Au-delà de ça, le niveau d’une équipe n’est jamais parfaitement homogène : certains sont d’excellents développeurs front-end, d’autres seront plus à l’aise sur le back-end, ou l’automatisation du projet. La code review est alors un excellent moyen de transmettre des compétences! Si la personne qui relit le code est plus expérimentée, elle sera à même de donner des conseils, des solutions plus élégantes et de repérer des problèmes. Si elle est moins expérimentée que celle qui a développé, elle pourra poser des questions, comprendre de nouvelles choses, s’inspirer. Et elle trouvera des erreurs aussi, c’est garanti!

C’est une procédure délicate, car il faut être capable de dire les choses sans blesser les autres (on est tous un peu sensible sur notre code), ou être capable d’admettre que l’on ne sait pas ce que fait cette méthode et de poser la question.

La code review permet aussi d’homogénéiser les développements, parce que cela force à relire le code des autres, ce que l’on ne fait que rarement si on est la tête dans le guidon. Et surtout, surtout, cela partage les connaissances fonctionnelles. Si vous avez connu le phénomène de « j’ai pas codé cette partie, je sais pas comment ça marche », vous savez de quoi je parle. Faire une revue de code force à comprendre les nouvelles fonctionnalités de l’application même si l’on a pas codé directement dessus. Cela limite ensuite le ‘Bus Effect’ (autrement appelé ‘Scooter Effect’ chez Ninja Squad, grâce aux aventures de Cyril).

Selon les projets et les clients, nous utilisons actuellement ces 3 façons de travailler. La dernière (un seul repo, avec une branche partagée par fonctionnalité, puis pull request pour intégration sur master) est vraiment agréable à utiliser.

Nous avons récemment commencé un projet avec ce workflow et notre intégration continue (Jenkins) se charge de construire chaque pull request indépendamment et d’inscrire sur Github un commentaire avec ‘Tests pass’ ou ‘Tests fail’. De plus nous pouvons déployer un container Docker pour tester une Pull Request de façon isolée. Je trouve ça génial : en 35 secondes l’application est buildée complètement, un container Linux isolé est démarré avec le nécessaire (serveur, bases et données), et l’application est exposée sur un port aléatoire. On se rend alors sur cette adresse pour tester la fonctionnalité et éventuellement remonter des bugs à l’auteur. Sans ouvrir un IDE, sans taper une seule ligne de commande, il est possible de lire le code, le commenter, voir si des tests échouent, et tester la fonctionnalité dans un environnement similaire à la prod. Magique.

Vous l’aurez compris, faire une pull request n’est pas très compliqué. Si vous démarrez un projet et hésitez sur la façon de travailler, pensez à considérer un workflow basé sur des pull requests et des revues de code : votre équipe finira par ne plus pouvoir s’en passer!