Archives du blog

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…

Getting started with lambdas – Part 2

Après une première partie dédiée à comprendre les interfaces fonctionnelles, nous allons entrer dans le vif du sujet avec cet article dont le but est de vous présenter les différentes façons d’écrire une lambda.

Supposons que nous ayons une interface Concatenator (histoire d’avoir un nom qui fait peur comme on sait faire en Java), qui prend un int et un double pour les concaténer :

interface Concatenator {
    String concat(int a, double b);                    
}

La première façon d’écrire une lambda implémentant cette interface sous forme de lambda sera :

Concatenator c = (int a, double b) -> { 
    String s = a + " " + b; 
    return s;
};

Voilà notre première lambda! Cette syntaxe est le fruit de nombreux mois de réflexion, après débat entre 3 propositions principales. On retrouve nos paramètres entre parenthèses avec leur type, suivi d’une flèche et d’un bloc de code entre accolades. Le bloc de code représente le corps de la fonction, c’est l’implémentation concrète de la méthode concat() de notre interface Concatenator. Ce corps de fonction est tout à fait classique avec un return en fin de bloc pour renvoyer le résultat.

Une autre façon, plus concise, d’écrire cette lambda est possible avec la syntaxe suivante :

Concatenator c = (int a, double b) -> return a + " " + b;

On note cette fois l’omision des accolades autour du bloc représentant la fonction. Cette syntaxe n’est bien sûr possible que si le corps de votre fonction tient sur une seule ligne, vous l’aurez compris.

Nous pouvons encore simplifier un peu l’écriture en utilisant un return implicite :

Concatenator c = (int a, double b) -> a + " " + b;

Le return a disparu ! En effet, par défaut, la valeur de l’expression à droite de la flèche est retournée par la lambda : les syntaxes avec et sans return sont donc parfaitement équivalentes.

Nous pouvons également nous reposer sur l’inférence de type et laisser le compilateur (lorsque c’est possible) déterminer les types de nos paramètres :

Concatenator c = (a, b) -> a + " " + b;

Vous voyez qu’une lambda peut être une expression très concise !

Si notre interface fonctionnelle avait une méthode avec un seul paramètre, par exemple :

interface UnaryOperator {
    int op(int a);
}   

Alors une lambda implémentant UnaryOperator pourrait être :

UnaryOperator op = (a) -> a * a;

Mais la lambda pourrait même ici se passer des parenthèses autour des paramètres :

UnaryOperator op = a -> a * a;

En revanche, une interface avec une méthode ne possédant pas de paramètres comme NumberSupplier :

interface NumberSupplier { 
   int get();
}

devra s’écrire :

NumberSupplier supplier = () -> 25;

Enfin, lorsque la lambda est un appel à une fonction de l’objet passé en paramètre, il est possible d’utiliser une syntaxe légérement différente. Ainsi, pour une interface fonctionnelle :

interface StringToIntFunction {                        
    int toInt(String s);
}

qui transforme une chaîne de caractères en entier, on peut écrire une lambda comme suit :

StringToIntFunction f = s -> s.length();

ou encore écrire :

StringToIntFunction f = String::length;

Ce :: est un nouvel opérateur Java : il agit comme un appel à la méthode length de l’argument de la méthode toInt. Un peu surprenant au début, mais on s’habitue vite. Cet opérateur peut également s’appliquer à un constructeur. Notre méthodetoIntpourrait donc également s’écrire :

StringToIntFunction f = Integer::new;

ce qui équivaut à

StringToIntFunction f = s -> new Integer(s);

L’opérateur peut aussi s’appliquer à une méthode statique, comme parseInt pour la classe Integer. La lambda :

StringToIntFunction f = s -> Integer.parseInt(s);

est donc identique à :

StringToIntFunction f = Integer::parseInt;

Enfin, il est aussi possible de faire référence à une méthode d’un autre objet. Si nous supposons l’existence d’une HashMapstringToIntMap dans notre code, nous pouvons écrire une lambda comme suit :

StringToIntFunction f = stringToIntMap::get;

qui signifie la même chose que :

StringToIntFunction f = s -> stringToIntMap.get(s);

Voilà, nous avons fait un inventaire exhaustif des façons d’écrire une lambda. La possibilité d’omettre les parenthèses, types, accolades et le mot clé return est appréciable et donne une syntaxe très peu verbeuse. L’ajout de l’opérateur :: introduit de nouvelles possibilités dans l’écriture comme vous avez pu le constater. Son utilisation demande un peu de pratique, mais cela viendra vite naturel !

La prochaine fois nous regarderons une petite subtilité sur la portée des variables utilisables dans une lambda. Teasing teasing…

Getting started with lambdas : Part 1

Si vous avez suivi l’actualité Java ces derniers temps, vous avez peut-être entendu que la sortie de la “developer preview” du JDK 8 a été repoussée. Bien sûr tout le monde s’en donne à coeur joie pour vanner Oracle, c’est de bonne guerre. Mais pour une fois, ce retard est peut-être une bonne chose : toute l’équipe du JDK travaille d’arrache-pied pour peaufiner la grande nouveauté de cette version : les lambdas. Nous avons suivi avec attention leur avancée ces derniers mois, testant des JDKs, pestant contre certains choix et en admirant d’autres. Si au début je trouvais un intérêt minimal aux lambdas par rapport à ce que proposent Scala et consort, j’avoue maintenant attendre la sortie de Java 8 pour profiter des nouveautés, et écrire du code un peu plus sympa dans un langage que j’apprécie.

Voilà assez parlé de ma vie.

Ce post démarre une série qui vise à présenter les lambdas, qui sont probablement la plus grande nouveauté dans le langage depuis les génériques. Plutôt que de vous montrer directement une lambda, et nous extasier devant leur utilisation, j’aimerais vous expliquer un peu ce qui se passe derrière.

Tout repose sur le concept d’interface fonctionnelle.

Une interface vous voyez ce que c’est : un ensemble de méthodes abstraites que l’on devra implémenter dans une classe. Jusque là ça va.

public interface MessageInterface {
  public String transform(String message);
  public void print(String message);
}

Mais cette définition change avec Java 8 : une interface peut maintenant avoir des méthodes concrètes et des méthodes statiques. Oui, oui, c’est nouveau. Le mot clé `default` est utilisé pour définir une méthode concrète dans une interface. Par exemple :

public interface MessageInterfaceWithDefault {
  public String transform(String message);
  public default void print(String message) {
    System.out.println(message);
  }
}

Ca fait bizarre, mais on s’y fait. Dans le cas de cette interface, la méthode `print()` a une implémentation par défaut. Il peut également y avoir plusieurs méthodes `default` bien sûr. Ainsi si vous voulez implémenter cette interface vous avez deux solutions :

public class MessageWithoutDefault implements MessageInterfaceWithDefault {
  public String transform(String message) {
    return message;
  }
  public void print(String message) {
   System.out.println(“message :” + message);
  }
}

Cette première solution implémente l’interface en donnant une implémentation à chaque méthode, la méthode `default` étant surchargée.

Une autre solution est possible, si l’implémentation par défaut de print vous convient, vous pouvez seulement fournir une implémentation à `transform()` :

public class MessageWithDefault implements MessageInterfaceWithDefault {
  public String transform(String message) {
    return message; // oui bon d'accord ça fait rien...
  }
}

Donc en résumé, une méthode `default` dans une interface vous fournit une implémentation par défaut, libre à vous de la redéfinir ou pas.

Qu’en est il de l’héritage multiple?

Si vous héritez de deux interfaces possédant une méthode `default` avec la même signature, le compilateur va regarder si l’une des interfaces hérite de l’autre. Si c’est le cas, l’interface la plus spécialisée est préférée. Sinon vous obtenez l’erreur de compilation suivante :

class training.lambda.Both inherits unrelated defaults for print() from types training.lambda.Interface1 and training.lambda.Interface2

Voilà pour les méthodes `default`.

Revenons-en aux interfaces fonctionnelles. Lorsque vous allez écrire une lambda, vous allez en fait implémenter une interface fonctionnelle. Une interface fonctionnelle est une interface qui ne possède qu’une seule méthode abstraite. Elle peut en revanche avoir plusieurs méthodes `default`. L’interface `MessageInterfaceWithDefault` est donc une interface fonctionnelle. Vous pourriez écrire :

MessageInterfaceWithDefault asALambda = message -> “message : “ + message;

Ce code est tout à fait valide. L’expression de droite est en fait l’implémentation de la méthode `transform()` de l’interface. Ainsi si vous exécutez le code suivant :

String result = asALambda.transform(“hello”); // result = “message : hello”

On est d’accord, il n’y a pas beaucoup d’intérêt à utiliser les lambdas ainsi. Cet exemple montre seulement ce que sont réellement les lambdas. Ainsi, vous ne pouvez pas utiliser les lambdas pour implémenter des interfaces qui possèdent plusieurs méthodes abstraites : le compilateur ne saurait pas quelle méthode vous essayez d’implémenter.

Le JDK contient déjà beaucoup d’interfaces fonctionnelles : `FileFilter`, `Runnable`, `Callable`, `ActionListener`, `Comparator`…

`FileFilter` a par exemple une seule méthode abstraite : `boolean accept(File pathname)`, qui prend donc un fichier en argument et renvoie un booléen. `FileFilter` est utilisé comme argument dans la methode `listFiles()` de `File`, pour renvoyer une liste de fichiers qui correspondent au filtre. Vous voulez récupérer les répertoires d’un dossier dir, en une ligne en utilisant les lambdas ?

File[] files = dir.listFiles(f -> f.isDirectory())

`f -> f.isDirectory()` est une lambda que le compilateur interprète comme l’implémentation d’un `FileFilter`. Rapide et efficace, je ne vous montre même pas le code que l’on doit écrire actuellement.

Dans votre code, vous pourrez faire vos propres interfaces fonctionnelles, qui seront joyeusement implémentées sous forme de lambda par vos collègues, parfois même dans des modules différents. Mais que se passe-t-il si quelqu’un ajoute une méthode abstraite à votre interface? Et bien les lambdas écrites par vos collègues vont poser problème à la compilation des modules qui utilise votre interface :

incompatible types: lambda.Interface1 is not a functional interface
multiple non-overriding abstract methods found in interface com.ninja_squad.training.lambda.Interface1

Pour prévenir ce problème, une annotation @FunctionalInterface a été ajoutée. Celle-ci indique au compilateur que l’interface en question ne doit avoir qu’une et une seule méthode abstraite. Si vous essayez d’ajouter une méthode abstraite à cette interface, vous obtenez l’erreur de compilation suivante :

Unexpected @FunctionalInterface annotation
training.lambda.Interface1 is not a functional interface
multiple non-overriding abstract methods found in interface training.lambda.Interface

Autant dire que ce garde-fou devra être systématiquement utilisé si vous créez des interfaces fonctionnelles afin de prévenir de potentiels (probables?) problèmes à l’avenir. Toute personne qui modifiera l’interface saura immédiatement à quoi s’en tenir!

La prochaine fois, on regardera comment écrire une lambda en détail (enfin!).

MongoDB Aggregation Framework

Vous avez probablement entendu parlé de MongoDb, une solution NoSQL orientée document développée par 10Gen. Les documents sont stockés en JSON, et bien que vous ayez un driver disponible pour chaque language, on se retrouve souvent à coder les requêtes en javascript dans le shell mongo fourni. Je vais vous parler de la version 2.2 qui est la dernière version stable et contient le framework d’aggregation, grande nouveauté attendue par les développeurs. Pour votre information, les numéros de version de Mongo suivent le vieux modèle du kernel Linux : les numéros pairs sont stables (2.2) alors que les versions de développement sont instables (2.1). Node.js suit le même modèle par exemple.

L’aggrégation donc, qu’est ce que c’est? Pour vous faire comprendre l’intérêt nous allons prendre un petit exemple (version simplifée d’un vrai projet). Admettons que vous stockiez les connexions à votre application toute les minutes, par exemple avec un document qui ressemblerait à

{"timestamp": 1358608980 , "connections": 150}

C’est à dire un timestamp qui correspond à la minute concernée et un nombre de connexions total.

Disons que vous vouliez récupérer les statistiques sur une plage de temps, par exemple sur une heure : il faudrait alors aggréger ces données pour obtenir le nombre total de connexion et le nombre moyen par minute. Seulement voilà, MongoDb ne propose pas de “group by”, de “sum” ou de “avg” comme l’on pourrait avoir en SQL. Ce genre d’opération est même déconseillé, car fait en javascript cela prend un plus de temps que dans une base classique. C’est en tout cas à éviter pour répondre à des requêtes en temps réel. Mais bon des fois, on est obligé…

 The old way : Map/Reduce
Jusqu’à la version 2.2 donc, on utilisait un algo map/reduce pour arriver à nos fins. Si vous ne connaissez pas, je vous invite à lire cet article de votre serviteur expliquant le fonctionnement. Dans un algo map/reduce, Il faut écrire une fonction map et une fonction reduce, qui vont s’appliquer sur les données selectionnées par une requête (un sous ensemble de votre collection MongoDb).

La requête qui permet de selectionner ce sous ensemble serait par exemple :

// stats comprises entre 15:00 et 16:00

var query = { timestamp : { $gte: 1358607600, $lte: 1358611200 }}

La fonction map va renvoyer les informations qui vous intéressent pour une clé. Ici nous voulons les connexions pour l’heure qui nous intéresse, donc nous aurons une fonction comme suit :

// on renvoie les infos pour la clé 15:00

var map = function(){ emit(1358607600, { connections : this.connections}) }

La fonction reduce va ensuite aggréger les informations, en ajoutant les connexions totales pour la clé 15:00 et calculer la moyenne associée.

// calculer la somme de toutes les connexions et la moyenne

var reduce = function(key, values){
 var connections = Array.sum(values.connections);
 var avg = connections/values.length;
 return { connections: connections, avg: avg}
 }

Maintenant que nous avons nos fonctions map et reduce, ainsi que la requête pour remonter les données qui nous intéressent, on peut lancer le map reduce.

// dans le shell mongo

db.statistics.mapReduce(map, reduce, { query: query, out: { inline: 1 }})

Le out inline permet d’écrire la réponse dans le shell directement (sinon il faut préciser une collection qui acceuillera le résultat). On obtient une réponse du style :

{connections: 180000, avg: 3000}

en 4,5 secondes environ sur ma collection de plusieurs millions de document légèrement plus complexes que l’exemple.

The new way : Aggregation Framework
Maintenant voyons la nouvelle façon de faire avec le framework d’aggrégation. Une nouvelle opération apparaît : aggregate. Celle-ci remplace mapReduce et fonctionne comme le pipe sous Linux : de nouveaux opérateurs sont disponibles et on peut les enchaîner. Par exemple, le “group by” est simplifié avec un nouvel attribut $group. La requête qui permet de filtrer un sous ensemble de la collection est écrite avec un opérateur $match. Enfin de nouveaux opérateurs viennent nous simplifier la vie : $sum, $avg, $min, $max… J’imagine que vous avez saisi l’idée.

Ici on veut un élément match qui limite l’opération aux données de l’heure concernée, on peut réutiliser la même query que tout à l’heure. On groupe ensuite les documents avec une seule clé : celle de l’heure qui nous intéresse, puis l’on demande le calcul de deux valeurs, le nombre total de connexions (une somme) et la moyenne des connections (une moyenne donc).

db.statistics.aggregate(
 { $match: query},
 { $group: { _id: 1358607600, totalCompleted: {$sum: "$connections"}, totalAvg: {$avg: "$connections"}
 }})

Le résultat est le suivant (en 4,2 secondes, soit un temps légérement inférieur au précédent) :

{ result: [{
 "_id": 1358607600,
 "totalCompleted": 180000,
 "totalAvg": 3000
 }], ok: 1}

L’avantage principal du framework d’aggrégation réside dans sa plus grande simplicité d’écriture et de lecture : plus besoin d’écrire des fonctions js soi-même pour des opérations somme toute assez courantes. Spring Data Mongo par exemple, le très bon projet de SpringSource pour vous simplifier la vie, demande d’écrire des fonctions en js pour faire du map/reduce. Vous avez donc un projet Java, qui contient quand même quelques fichiers js au milieu pour faire certaines opérations. Beaucoup attendent donc avec impatience l’arrivée du support du framework d’aggrégation dans Spring Data. Espérons qu’il ne tarde pas trop! En attendant d’autres frameworks comme Jongo l’ont déjà intégré. Il y a toutefois quelques limites comme le résultat de l’aggregate qui doit faire moins de 16Mo. Bref tout n’est pas idéal, mais ce très bon produit s’améliore à chaque version!

Scala on Coursera

La semaine dernière s’achevait le cours Functional Programming Principle in Scala de Coursera, animé par Martin Odersky en personne. Si vous ne connaissez pas Coursera, sachez que c’est l’une des startups californiennes qui se lance dans le domaine de l’éducation en ligne (l’une de leur dernière recrue est Pamela Fox, speakeuse à Mix-it 2012, et qui, alors qu’elle n’était pas encore employée, avait fait une keynote sur l’éducation). Sur le site, vous suivez des cours en vidéo, vous avez des exercices à faire et à rendre, vous recevez des notes et à la fin un diplome si vous avez été sages. Avec pas loin de 2 000 000 d’inscrits, le site a pris son envol, à juste titre il faut dire car la plateforme est très bien conçue. Martin Odersky, et sa société TypeSafe, frappe donc encore un grand coup marketing en lançant ce cours en ligne sur Coursera. Si ce nom vous est également inconnu, Martin est le créateur de Scala avec une équipe de l’EPFL (Ecole Polytechnique Fédérale de Lausanne) où il est chercheur. Il a également bossé sur le compilateur Java et notamment contribué aux génériques de Java5. On peut donc dire sans trop se tromper qu’il en connaît un rayon en matière de JVM et de langage.

 

Je ne l’avais jamais vu en revanche donner un cours, mais les videos sur Coursera qu’il a réalisé sont claires et compréhensibles à condition d’avoir un minimum d’anglais (et également de faire abstraction de l’accent allemand, qui est quand même plus compréhensible que l’accent français probablement). Le volume de cours n’est pas négligeable : s’étalant sur 7 semaines, il fallait quand même prévoir une à deux heures pour les vidéos et de quelques minutes à plusieurs heures pour les exercices. Mais cela n’a pas décourager les foules : le cours a compté 50000 participants (ou plutot inscrits, je ne sais pas si tous en sont venus à bout). Ce que j’en retiendrais :

 

Les plus :

– la plateforme Coursera : rien à dire, je trouve ça bien très bien fait. Les vidéos sont téléchargeables ou visionnables en ligne, avec une possibilité d’accélérer la lecture qui est très appréciable tout en restant compréhensible. Les exercices sont très clairs, vous téléchargez un projet tout prêt dans le cas de ce cours, une fois terminé, vous pouvez le soumettre en ligne de commande avec ‘submit monmail monpassword’. Des tests unitaires vont alors se lancer sur votre projet directement sur la plateforme et vous pouvez voir votre résultat sur la page de feedback. Il faut patienter quelques minutes mais rien de dramatique. Le système de note est intéressant, avec un petit côté gamification : on cherche à avoir le 10/10 même si une note inférieure permet de valider le cours. Seul point négatif à ce propos : l’absence de trace vraiment explicite pour comprendre quel test et quand votre programme a échoué : on se retrouve à mettre de vieux println dans le code pour essayer de cerner le problème.

– les leçons étaient très souvent intéressantes, mettant bien en avant la programmation fonctionnelle, avec des exemples bien choisis et des solutions élégantes. J’avais lu le livre d’Odersky “Programming in Scala” lors de sa sortie, et j’ai retrouvé des exemples du livre, mais je m’y suis bien moins ennuyé. Les exercices étaient loin d’être triviaux pour certains : celui sur les anagrammes que je pensais faire en quelques minutes m’a finalement pris les 2h de ma pause déjeuner… La progression était correcte, et j’ai eu l’impression d’apprendre des choses tout au long du cours : je pouvais difficilement en demander plus.

– au delà de Scala, difficile de ne pas aimer la programmation fonctionnelle. Et la pratiquer en Java est un vrai plaisir. Les collections scala sont géniales, vraiment. Dans la vie de tous les jours, je pallie comme beaucoup le manque grâce à l’excellente librairie Guava par exemple, et ce n’est pas sans déplaisir que je vois l’arrivée de Java8 (dont de nombreux concepts sont déjà dans Scala).

 

Le moins :

– Certains exercices étaient plus “mathématiques” que “programmatique”, j’avais l’impression de retourner en prépa plus que d’apprendre un langage. On sent ici le côté académique de Odersky et je me demande si cela n’a pas rebuté un certain nombre de participants. Cela se sent aussi sur le langage en lui même, avec son système de type. Ce n’est pas le genre de chose qui m’intéresse outre mesure (que le système de type soit complet ou pas…), et certaines vidéos à ce sujet étaient moins intéressantes à regarder.

– Je me suis limité à utiliser l’IDE conseillé, un Eclipse packagé pour Scala. Et j’ai trouvé l’expérience horrible (je travaille pourtant très souvent sous Eclipse), l’IDE plantait régulièrement, la complétion était longue, les erreurs souvent obscures et lancer les tests était lent. Autrement dit je ne sais pas comment les équipes qui travaillent sur des projets conséquents se débrouillent pour être productives. Il est fort possible qu’il y ait eu un problème avec ma machine, mais j’ai un macbook avec jdk7 assez standard : j’imagine donc que d’autres peuvent avoir ce problème. J’ai vu que beaucoup utilisait TextMate, et IntelliJ pour certains, ce qui est certainement mieux mais pas toujours possible dans une entreprise. Et globalement tout est lent, la compilation, les tests, l’execution… TypeSafe fournit un gros travail à ce sujet mais il y encore du chemin à parcourir.

– J’ai souvent cherché des solutions alternatives une fois mes exercices rendus et je me suis rendu compte que même en connaissant très bien le problème, j’avais parfois du mal à comprendre celles-ci, tant les possibilités et styles peuvent varier. Je trouve ça assez inquiétant pour la maintenabilité d’une application, en tout cas si personne ne prend le temps de bien fixer certaines règles. La liberté amenée par Scala vient avec un prix de rigueur, Odersky le dit lui même dans ses vidéos, n’hésitez pas à nommer les résultats intermédiaires de vos programmes. Et c’est vrai que l’API donne parfois envie de chaîner les appels sur une ligne, il faut donc résister et accepter de perdre en “oneliner” pour gagner en lisibilté.

– Les boucles “for comprehension” sont un concept puissant mais on se retrouve vite perdu entre les types disponibles, les itérateurs déclarés et les filtres. Alors que le code executé est souvent simple, toute la logique se trouve dans la déclaration du for. C’est souvent compliqué à débugger, parfois correct mais incroyablement lent si vous avez fait un mauvais choix (dont on ne se rend pas toujours compte immédiatement). Pour les anagrammes j’avais par exemple une solution qui fonctionnait correctement mais qui mettait 30 secondes de plus pour un itérateur mal déclaré. Il doit y avoir des carnages dans certaines applications… Il est parfois plus simple de faire le code avec des “map” et des “filter” puis de convertir en “for comprehension” par la suite.

 

Si le sujet vous intéresse un autre article bien plus complet sur Scala et Coursera se trouve ici. Je ne peux qu’admirer l’excellence marketing de TypeSafe qui réussit encore une fois un très beau coup (après l’annonce récente de l’entrée de Rod Johnson au board par exemple). Et à titre personnel, je suis content d’avoir participer : j’ai appris de nouvelles choses et voir d’autres langages est toujours un excellent moyen de progresser. Je ne suis par contre toujours pas convaincu pour faire un vrai gros projet de la vraie vie avec. Ou alors avec un mec de chez Twitter ou Foursquare qui vient m’aider à démarrer et à prendre les bonnes options et les bonnes pratiques. Mais on en a rarement sous la main. Je surveille quand même du coin de l’oeil, on ne sait jamais…

JUGSummerCamp 2012

Premier voyage de l’équipe NinjaSquad, direction La Rochelle pour le JUG Summer Camp. Du Java, du Web, l’océan, une conf gratuite d’une journée avec une organisation irréprochable, il faudrait être difficile pour ne pas aimer!

JUG Summer Camp 2012

Keynote : Nicolas de Loof – @ndeloof

Nicolas nous a fait un numéro de stand up très drôle en parodiant le podcast bien connu dans le monde Java : les Castcodeurs. Comme aucun d’entre eux n’étaient présents, Nicolas a eu l’idée de faire un puppet show en reprenant les traits caractéristiques de chacun d’entre eux, pour faire une keynote originale sur notre métier. Franc succès dans la salle (évidemment seulement drôle si on écoute ce podcast).

La journée se déroule ensuite sur deux tracks de confèrence, il faut donc faire des choix.

Google TV : Olivier Gonthier – @rolios

Première présentation sur la Google TV, petit boîtier qui permet de faire tourner des applis Android sur votre télé, mais pas encore disponible en France (on ne connait même pas les partenariats avec les opérateurs). Le principe est simple : une prise HDMI en entrée reçoit le flux vidéo et une prise HDMI de sortie le renvoie vers la TV. A noter que le code de Google TV n’est pas open source. Sinon techniquement c’est le même market que les applis Android traditionnelles.

Commençons par le point qui fâche et qui, à mon sens, fait perdre tout l’intérêt de la chose : il n’est pas possible de récupérer le flux video, ni la chaine visionnée par l’utilisateur, donc vous pouvez oublier toutes les idées d’applications contextuelles: IMDB sur le film en cours ou les stats du match que vous êtes en train de regarder, c’est foutu!

Mais il y a deux ou trois trucs intéressants quand même : par exemple, le « second screen app« , qui permet aux devices Android de s’interfacer avec la GoogleTV et de vous servir de télécommande ou mieux, d’écran annexe pour certaines applications. L’exemple que je trouve assez cool : un jeu de poker Hold’em où la TV affiche la table de jeu (avec les cartes communes et les mises) et chaque joueur voit ses cartes sur son téléphone. Ce genre d’application peut avoir un grand potentiel, je suis sûr que l’on va voir apparaître des applications géniales!

Le développement est de la programmation Android traditionnelle, le SDK étant complété avec des fonctions pures TV (touches telecommande par ex). Si vous souhaitez développer une application Android utilisant le « second screen », vous pouvez utiliser Anymote library (voir dans les exemples de code fournis par Google, dans l’application Blackjack TV).

Il est également possible de développer des applications en html5, la GoogleTV ayant un très bon navigateur Chrome intégré (très bien documenté d’après le speaker). Il est aussi possible de packager votre application avec Phonegap pour la distribuer directement sur le Market.

En plus j’ai gagné la GoogleTV du concours, yay!

Node.js : Romain Maton – @rmat0n

Romain faisait une présentation générale de Node.js (voir articles précédents et les excellents articles de Romain) avec quelques rappels sur les principes de base. C’était une présentation très orientée web-app avec le framework web Express et son moteur de template par défaut Jade (cf article précédent également).

Puis les modules importants :

– l’incontournable Socket.io pour faire des websockets

– logging avec Winston

nodemon, redémarrage automatique dès que vous modifiez un fichier.

forever pour relancer l’application en cas d’erreur qui coupe l’appli

jasmine, qunit pour les tests

Et pour terminer une petite démo sympa avec la librairie speak qui fait parler le navigateur pour annoncer le prochain bus qui passe.

Start me up : Nicolas de Loof – @ndeloof

Après le buffet repas le plus incroyable pour une conf que j’aie vu (les membres de l’orga Mix-it présents étaient impressionnés), on reprend avec ‘Start me up’ ou comment passer rapidement de l’idée à la réalisation (en utilisant Cloudbees, dont Nicolas est employé). L’idée est ici de faire un mini moteur de recherche sur les talks de la conf. Nicolas utilise au passage un autre service dans le cloud que je ne connaissais pas : WebSolr, un Solr as a Service. Cloudbees on aime bien, Mix-it est hébergé gracieusement dessus et ça marche très bien (le support a toujours été très réactif en cas de problème).

La présentation est intéressante, Nicolas étant un bon speaker, mais si vous avez déjà vu une présentation de Cloudbees le contenu ne vous surprendra pas (comment déployer, comment gérer ses instances, comment déclarer des propriétés pour le déploiement etc.). La nouveauté la plus notable est sans doute le Click Start, qui permet en un clic de créer tout ce qui va bien pour un type d’application (squelette du projet, repository de code, instance jenkins, base de données et instance de run). Pour l’instant, quatre types de Click Start sont disponibles (JavaEE6, Hibernate/Tomcat, Rest/Backbone, Scala/Lift).

Du legacy au cloud : David Gageot – @dgageot

David est un excellent speaker que je vous recommande de voir si il est dans une conférence à laquelle vous assistez. Son talk est du pur live coding, sans aucun slide, et reprenait le kata de Gilded Rose où une application existante doit être refactorée.  Une spécification est disponible, mais David ne recommande pas particulièrement de la lire pour commencer mais plutôt de créer des tests sur le code existant que l’on doit retravailler. La logique étant que si l’application convient aux utilisateurs actuellement, le plus important est de préserver son fonctionnement. Les tests sont assez simples à écrire, on appelle chaque méthode et on colle dans le assert le résultat renvoyé : on obtient ainsi une série de tests au vert qui seront notre sécurité.

David utilise le plugin infinitest qui relance les tests dès que le code est modifié : si vos tests sont très courts, le feed-back est immédiat.

La marche à suivre pour refactorer le code est la suivante :

– augmenter la symétrie (mettre les if/else et les equals de la même façon, en enlevant les conditions inversées par exemple).

– puis faire apparaître les duplications de code afin d’extraire de nouvelles méthodes

David finit par introduire de la délégation (un objet était passé dans toutes les méthodes de la classe), en utilisant une annotation de Lombok.

Une fois le code propre, David écrit un petit serveur http qui expose les données en JSON, déploie l’application sur heroku, puis déploie un front statique sur Github Pages (comme le blog de NinjaSquad) qui consomme les données.

Le tout en 45 minutes, en expliquant très bien ses choix et en utilisant IntelliJ avec maestria. C’est la présentation que j’ai préféré de la journée, même si parfois le refactoring était un peu magique, David connaissant bien le code et étant pressé par le temps. Si vous voulez tester le dojo par vous même, les projets sont disponibles sur le compte Github de David.

Beaglebone = Arduino^10 : Laurent Huet – @lhuet35

Laurent nous faisait descendre de quelques niveaux d’abstraction avec un talk sur Beaglebone, une carte plus puissante qu’un Arduino, un peu du même type que le Raspberry Pi. La présentation était intéressante, avec une explication générale des principes, une démo, et les technos que l’on peut faire tourner sur ce type de cartes (C/C++, Java, Python, Node.js …). Manque de chance pour Laurent, sa carte de démo avait grillé la veille (les risques du métiers), mais son talk n’en a pas été trop perturbé, bravo à lui!

Programatoo pour les grands : Audrey Neveu – @audrey_neveu et Ludovic Borie – @ludovicborie

Vous avez peut être entendu parler de Programatoo, un atelier de programmation pour initier les enfants dès l’age de 6 ans aux joies du code. Audrey et Ludovic nous ont montré les différents outils que l’on peut utiliser pour  éveiller la curiosité des plus petits (je ne sais pas si cela peut fonctionner avec vos collègues également) : Scratch, KidsRuby ou encore TortueScript. Très sympa, si vous avez des enfants, ce genre d’outils devraient vous intéresser!

La journée de conf se termine déjà, l’assemblée se dirige vers le port pour un repas tous ensemble. Le JUGSummerCamp aura été une très belle journée, superbement organisée par Jerôme Petit, Orianne Tisseuil et leur équipe. L’équipe Mix-it en partie présente compte bien leur emprunter quelques bonnes idées! Si vous avez l’occasion de vous rendre à la prochaine édition, n’hésitez pas, la conférence, gratuite, est l’une des toutes meilleures en France et la Rochelle et ses alentours ne manquent pas de charme pour rester quelques jours supplémentaires!

Getting started with Apache Camel : Part 1

Je voulais écrire un court billet sur les tests dans Camel. Puis je me suis rendu compte que je n’avais jamais évoqué Camel sur ce blog. Ce qui est un peu étrange vu que c’est le framework que j’utilise tous les jours, sur plusieurs projets, depuis plus d’un an. Et que c’est l’un des outils les plus cools et les plus indispensables pour garder votre intégrité mentale dès qu’il s’agit de router des messages entre différentes machines/protocoles/wtf has imagined the architect guy before you.

Donc je vais vous raconter comment on peut faire des trucs géniaux dans Camel. D’abord le nom complet est Apache Camel, un projet qui fête ses 5 ans, avec pas mal de contributeurs, dont une grande partie vient de la société FuseSource (récemment acquise par RedHat). Pas vraiment de soucis à se faire sur la maturité du projet donc. Mais à quoi ça sert ? Il faut voir Camel comme un routeur de messages entre vos différents applicatifs, certains appelleront ça un ESB léger. D’ailleurs Apache Service Mix, qui est l’artellerie lourde en matière d’ESB Apache se base sur Camel pour sa gestion des routes. D’autres appelleront ça un framework d’intégration, à la Spring Integration mais en plus complet et plus agréable à utiliser. D’ailleurs si vous êtes un fan de Spring, aucun problème l’interopérabilité est vraiment excellente.

Les introductions à Camel me laissent toujours un peu sur ma faim, sans doute parce que ce n’est pas au premier coup d’oeil que l’on comprend sa puissance. Mais au fil des projets, on tombe sur souvent sur des use cases qui correspondent exactement à ce que propose Camel dans un de ses nombreux modules ou patterns, et c’est la que la magie opère. Ce n’est pas rare que l’on me demande d’ajouter une fonctionnalité et que Camel permette de répondre : ‘Pas de problème, il y a un pattern qui fait exactement ça’.

Il faut un peu de temps pour se faire au fonctionnement et appréhender les différents patterns. Car, au début, Apache Camel à été créé comme une implémentation Open Source des EIPs (Enterprise Integration Patterns), qui sont à peu près aussi chiants à lire que les Design Pattern : tant que l’on n’en a pas eu besoin ça n’a pas vraiment de sens.

Organisation
Quand vous démarrez un projet, vous n’avez besoin que d’une seule dépendance : camel-core (actuellement en version 2.10.x). Elle contient les fameux EIPs de base ainsi que la gestion des protocoles les plus courants (fichier par exemple). Ensuite si vous voulez faire quelque chose d’autre comme des appels ftp, il faut ajouter le module correspondant, camel-ftp, dans vos dépendances. La liste des modules disponibles est impressionante : vous pouvez interagir avec tout ce dont vous pouvez avoir besoin : de MongoDb à un AS400 en passant par un LDAP, Nagios, JDBC, des flux RSS… Il y a également des modules qui ne sont pas dans le repo officiel (c’était le cas des Websockets jusqu’à peu encore) car ils sont en cours de stabilisation, ou d’autres pour des problèmes de licence (module SAP par exemple). Tous les protocoles réseaux sont également gérés. Bref il faut faire quelque chose de très très exotique pour ne pas trouver son bonheur.

Pour avoir modestement contribué à quelques bugfixes et features, le code du core est très bien pensé, écrit et testé. Les modules sont eux de qualité un peu plus variable, mais tous ceux couramment utilisés sont très bien faits et production-ready.

A quoi ca ressemble une route ?
Ces routes peuvent être écrites en XML, mais comme 95% des développeurs je trouve ça pas terriblement fun, j’utilise l’autre alternative, la DSL fournie par Camel, qui permet d’écrire les routes directement en Java (qui a en plus l’immense avantage de vous donner l’autocomplétion dans votre IDE). C’est un peu perturbant au début, parce que l’on écrit pas des méthodes comme dans un projet classique, on écrit la déclaration des routes que les messages vont suivre dans l’application.

Par exemple :

from("file://inbox?delete=true").to("bean:handleOrder").to("file:outbox");

Voilà, ça c’est une route. Basique certes, mais qui permet de récupérer un fichier dans un répertoire inbox, d’envoyer son contenu (que l’on imagine être une liste de commande) à un bean Java qui s’occupera de les traiter, avant de placer le fichier de commandes traitées dans un répertoire outbox.

Même si on a jamais fait de Camel de sa vie, la DSL se lit assez bien, une déclaration de route se fait de la façon suivante :
– un point d’entrée (identifié par le ‘from’) qui s’appelle un Endpoint en langage Camel. Le triplet de déclaration d’un endpoint est souvent le même à savoir un protocole (ici ‘file’), un nom (ici ‘inbox’ qui correspond au répertoire) puis des options après le ? (ici pour indiquer que les fichiers sont supprimés après lecture)
– un ensemble d’étape (identifiés par ‘to’), la dernière étant le point de sortie, sur le même modèle.

Dans cette route il n’y a pas de pattern particulier, c’est une route basique du type ‘mon message va de là à là’. Camel va se charger pour vous de faire les conversions de type nécessaire. Si les commandes sont en xml dans le fichier, il va convertir le xml en objets Java pour pouvoir appeler le bean de traitement de commande, puis reconvertir en xml pour les placer dans le fichier de sortie.

Admettons que maintenant votre système de commande expose également un webservice REST qui doit appeler le même bean et également pousser le fichier de commandes traitées dans le répertoire outbox. Easy! D’abord on découpe la route précédente en 2, grâce au mot clé ‘direct’ qui est en fait un moyen de créer des sous routes.

from("file://inbox?delete=true").to("direct:orders");
 from("direct:orders").to("bean:handleOrder").to("file:outbox");

Maintenant ajouter le webservice se résume à créer une route qui écoute les requêtes entrantes grâce au module cxfrs pour du REST et qui appelle la route direct:orders

from("cxfrs:bean:orderRest").to("direct:orders");

Il y a bien sûr un peu de code pour indiquer à cxfrs que l’on attend les requêtes sur tel port avec tels paramètres, mais la route en elle-même se réduit à ça.

Pattern
Avant de voir un premier pattern, il faut comprendre comment sont organisés les messages dans Camel. Nous avons vu que la déclaration de route est une suite d’étapes. Entre chacune de ces étapes, l’objet qui va transiter est un Exchange, qui contient un message In et un message Out. A chaque étape l’exchange entre avec le message In rempli et le message Out vide, puis la partie Out va être remplie avec le résultat de l’étape. Lors de l’étape suivante, ce message Out va devenir le message In et ainsi de suite. Une fois que l’on a compris ce principe de chaine (un out devient le in de l’étape suivante, qui remplit le out, qui devient à son tour le message in de l’étape suivante etc…), tout devient très simple. Un message en lui même est composé d’un ensemble de header et d’un body.

Donc si vous voulez utiliser un pattern Camel comme par exemple filtrer les messages, vous utilisez la fonction filter dans la DSL

from("direct:orders").filter(header("filiale").isEqualTo("Europe")).to("direct:europe");

Si vos commandes de la filiale Europe doivent subir un traitement spécial, vous pouvez filtrer les messages sur ce header. Camel fournit pas mal de méthode pour établir ces filtres de façon simple (ici sur un header), mais vous pouvez également appeler une méthode de votre métier pour filtrer.

Allez, un dernier exemple de pattern moins connu que filter et qui sert beaucoup : ‘recipientList’. Il permet de router dynamiquement un message.
Par exemple :

from("direct:orders").recipientList(header("filiale").prepend("direct:"));
 from("direct:europe").to(...);
 from("direct:asie").to(...);

Camel va appeler la sous-route qui correspond à la bonne filiale. Si vous ajouter une nouvelle filiale dans votre SI, vous avez seulement à écrire la sous route qui correspond. C’est pas cool ça?

J’ai encore des dizaines de trucs géniaux sur Camel, mais on va s’arrêter là pour aujourd’hui et on reprendra la prochaine fois. Stay tuned!

Play tips – Test with an embedded mongodb

Si il y a deux outils que j’affectionne en ce moment, c’est bien Play! (v1.2.5, la v2 ne m’a pas encore convaincu) et MongoDB. Pour ceux qui ne connaissent pas Mongo, c’est une base de données NoSQL orientée document qui écrase un peu la concurrence actuellement. Pour synthétiser les points forts de celle-ci en quelques lignes (car ce n’est pas le sujet de ce billet), on vous dira que :

– MongoDb n’a pas de schéma, vous n’avez qu’à envoyer un objet en JSON, et il stocké, point barre.
– MongoDB va stocker votre objet comme un document en BSON (un encodage binaire du JSON)
– MongoDB vous donne une API javascript pour faire des requêtes, mais des drivers sont existants dans la plupart des languages.
– MongoDB est très performant. Et qu’en plus si une instance ne suffit pas en prod, vous pouvez en mettre plusieurs, et le sharding (la répartition de vos données entre les différentes instances) se fait tout seul.
– Mongo gère la réplication entre instances, mais également la consistence de votre base (ce qui n’est pas le cas de toutes les bases NoSQL) à travers un fichier de log des opérations entre autres.
Et globalement tout ceci est assez vrai. Mongo n’est surement pas la base de données ultime mais elle rend de très bons services si l’on a des choses un peu volumineuses à stocker.

Si vous avez testé Play!, vous avez surement déjà remarqué le système de persistence assez bien foutu. On annote une entité, on lui fait étendre une classe Model et ça roule. Et bien, pour MongoDB c’est à peu près la même chose.

Vous devez commencer par ajouter Morphia dans les dépendances du projet. Morphia (hébergé sous google code, si je vous jure, ça existe encore) est un petit ORM Java/MongoDB qui marche pas mal, et justement un module Play existe. on édite donc le fichier dependencies.yml pour ajouter Morphia.

 - play -> morphia 1.2.9

Un petit coup de “play deps” en ligne de commande pour récupérer le module et nous sommes prêts. Dans votre projet, prenez (ou créez) une entité, par exemple App

Si on ajoute un simple test unitaire

et qu’on le lance, le test échoue lamentablement à se connecter à votre MongoDB. Normal! Et le but de ce billet et de vous montrer comment lancer ces tests d’intégration sans installer MongoDB sur une machine. Pour cela une petite lib très pratique existe : embedmongo. Vous pouvez l’ajouter dans votre fichier de dépendances :

- de.flapdoodle.embedmongo -> de.flapdoodle.embedmongo 1.16

Nous devons compléter notre test unitaire pour démarrer une instance Mongo avant le test. La plupart des articles illustrant l’utilisation de cette librairie montre des exemples de tests unitaires où l’instance est démarrée dans une méthode annotée @BeforeClass (qui, comme vous le savez sans doute, sera executée avant les tests). Mais Play! fonctionne un peu différement puisqu’un test unitaire Play! (qui étend la classe UnitTest) démarre en fait l’application avant de lancer la classe de tests et notamment les plugins utilisés comme Morphia. Si nous utilisons une méthode annotée @BeforeClass , le test va échouer car Morphia ne parviendra pas à se connecter à l’instance embarquée qui ne sera pas encore démarrée. Un moyen simple de contournement est de créer notre propre classe de base pour les tests unitaires qui utilisera notre Test Runner plutôt que celui par défaut de Play! En fait, notre Runner va tout simplement étendre le Runner de base mais démarrera l’instance Mongo avant de démarrer Play! Get it ?

Voila donc notre classe de base de test (qui remplace UnitTest et utilise donc notre propre runner de tests)

et notre Runner, qui démarre l’instance avant d’appeler le runner de Play!

Notre test devient

Tadam! Cette fois le test fonctionne!

Enjoy!

Un an de hype!

Après plus d’un an de blog, et 18 articles, voici le moment idéal de faire un petit résumé des thèmes abordés en 12 mois de hype!

Node
Pas mal de Node.js, peut être le sujet le plus hype de l’année, avec une série d’articles d’introduction :
Getting started with Node.js (part 1)
Getting started with Node.js (part 2)
Un complément à cette série avec la présentation du framework web Express (et mise en oeuvre avec un exemple dispo sur github) : Node, Express et Jade.
Si vous voulez coder, il faut également un IDE pratique : Cloud9 propose un outil en ligne, prévu pour faire du node.js.
Enfin deux billets autour de l’actualité de Node et de son écosystème :
Trello qui utilise Node (de façon assez étrange l’article le plus lu de l’année avec plusieurs milliers de lecture)
– La sortie d’un framework full stack : Meteor.js, assez intéressant pour son côté temps réél intégré.

Hadoop
La deuxième série d’article a été écrite pour le magazine Programmez et publiée en Septembre dernier. Hadoop est un incroyable outil, si vous voulez le découvrir :
Getting started with Hadoop (part 1)
Getting started with Hadoop (part 2)

Le site Mix-it
Une partie du succés de Mix-it de cette année est dû au site communautaire mis en place, que nous avons développé avec amour :
Le pourquoi
Le comment (avec plein d’outils sympas dedans).

Less
Ou comment le combo Less et Twitter Bootstrap va changer votre vie de développeur web : CSS sucks, do Less!

Play!
Sans avoir d’article vraiment consacré, Play! se retrouve un peu partout avec notamment un article assez lu sur l’annonce de la 2.0 beta à Devoxx :
Back from Devoxx : Play! 2, hopes and fears
Vous trouverez aussi des traces de Play! dans l’article consacré à Typesafe

Des retours de conf
De la What’s next de l’année dernière à fOSSa en passant par Mix-it (vu du côté orga, comment choisit-on les sessions)

Cast-it
Le podcast qui parle Java, mais pas que, continue! Si vous n’avez pas écouté depuis l’annonce, jetez-y une oreille, l’année fut bien remplie avec des invités locaux et internationaux (Romain Guy, Pamela Fox, Guillaume Laforge…)!

Thanks all for reading!


Le site Mix-it : making-of

Mix-IT est terminé et beaucoup de participants ont apprécié le nouveau site avec ses facettes communautaires et social gaming. En tout cas, nous avons pris beaucoup de plaisir à le faire. Car oui, ce site a été entièrement développé par les soins de notre équipe, particulièrement par Cyril Lacote (qui, il faut le dire doit avoir 60% du code à lui seul), Agnès Crépet et moi même, aidé par le reste de la team, avec leurs propositions, tests et feedback.

Voici donc une liste non exhaustive des outils et technos utilisés :

Trello : nous sommes des fans de la première heure de cet outil, qui nous a beaucoup servi pour échanger (mes camarades globe trotteur étant toujours décalés de plusieurs heures). Trello permet de faire un scrumboard interactif (on est notifié des échanges sur une tache), temps reel, avec un système de vote, label et filtre. Ça n’est pas JIRA mais pour un outil gratuit, c’est un outil génial.

Github : les sources du projet sont gérées sous Git. Aucun d’entre nous n’est un expert mais nous n’avons pas rencontré de problème majeur passés les premiers réglages. Nous avons utilisé le modèle décrit par Github (voir le talk de Zach Holman, et les articles GitHub), a savoir des pull requests, revues par un autre développeur avant d’être acceptées dans le master. C’est une bonne façon de garder une ‘collective ownership’ du code, même sans commiter.

Cloudbees : l’application est hébergée gracieusement par Cloudbees, qui a de plus acceptée généreusement de nous offrir les services additionnels qui nous était nécessaires (SendGrid, base de données en mode étendu, application en mode On Demand). La plateforme est très bien réalisée, le déploiement prend quelques minutes et est très simple à configurer. Ajoutez à ça un support ultra réactif et le fait qu’un déploiement est invisible pour les utilisateurs et vous avez une plateforme de choix pour vos développements.

Techniquement, l’application est codée avec le framework Play! (1.2.4 à l’heure actuelle) : rien à dire là dessus, Cyril et Agnès ne connaissaient pas et étaient productifs en quelques heures, peu de problèmes rencontrés, et avec tout un tas de modules à disposition (recherche full text Lucene, export PDF, parser Markdown). Bref, un outil génial! Un peu de Guava en plus et nous avions nos briques côté serveur. La base de données est un MySQL (hébergement cloudbees oblige).

Côté client, rien de très original, du bon vieux jQuery pour la manipulation de DOM. Et pour faire la même chose côté serveur (en Java donc), nous avons utilisé Jerry, qui nous permet de manipuler le contenu HTML des posts Google+ pour transformer les mentions d’utilisateurs. Nous avons également utilisé un plugin jQuery bien pratique pour gérer la dirtiness des formulaires et empêcher la sortie des pages en cours d’édition : dirtyforms.

Twitter Bootstrap : probablement notre coup de coeur, car même si nous faisons tous du développement, aucun d’entre nous n’est très doué en CSS. Et là, Twitter Bootstrap peut vous sauver : c’est un bootstrap CSS qui vous donne juste ce qu’il faut de cadre pour faire une application web présentable. Inconvénient : beaucoup de sites utilisent la même chose, il faut donc faire un peu de customisation pour différencier votre site. Tous les icones utilisés proviennent de fontawesome. Nous utilisons la version Less de Bootstrap plutôt que la version CSS : pour plus d’infos voir article précédent.

Ce qui n’a jamais atteint la mise en ligne

Nous avions envie de mettre un peu de communication temps réel sur le site avec un système de notifications lorsqu’un participant auquel vous étiez relié effectuait une action sur le site. Pour ça, un projet annexe (disponible sur github également) utilisant nodejs était utilisé. Dès qu’une action était effectuée sur le site, une requête était envoyée à un serveur nodejs, qui notifiait les utilisateurs intéressés connectés (par websocket en utilisant socket.io). La notification se fait sous forme d’une notification HTML5 si disponible dans le navigateur, ou en utilisant le plugin noty. Malheureusement nous n’avons pas eu le temps de terminer cette fonctionnalité.

Maybe next year… D’ici là, vous pouvez trouver les sources sur Github et vous amusez avec!