Utilisation de Scala pour simplifier une application PrimeFaces + Cassandra

Suite à la publication de cette article, un deuxième billet a été publié, cette fois-ci en utilisant Groovy

Si vous avez suivi un peu l’actualité d’Ippon de ces derniers mois, vous avez dû constater qu’il y a deux technologies qui me plaisent particulièrement en ce moment :

  • PrimeFaces, une bibliothèque de composants JSF moderne et performante
  • Cassandra, une base de données NoSQL orientée colonne

Jusqu’à présent, et comme certainement 99% de la population de développeurs, j’utilisais ces technologies avec le langage Java. Cependant, la mode étant aux langages alternatifs, j’ai voulu faire un essai et utiliser Scala à la place de Java : je vais donc vous présenter ici cette application de test, et discuter des avantages et inconvénients rencontrés.

Préparation du jeu de test

L’application de test est un simple tableau JSF, affichant des données provenant d’une Column Family Cassandra.
Pour avoir cette Column Family fonctionnelle :

  1. Clonez notre repository Tatami : https://github.com/ippontech/tatami
  2. Dans une console, lancez Cassandra : “mvn cassandra:run”
  3. Dans une autre console, lancez Jetty : “mvn jetty:run”
  4. Vous pouvez maintenant utiliser Tatami en vous connectant sur http://127.0.0.1:8080 : créez quelques utilisateurs depuis la première page. Puisque nous n’avons pas configuré de serveur SMTP, vous verrez dans les logs de Tatami le mail envoyé, avec le mot de passe généré. Vous pourrez alors vous logger dans l’application pour indiquer votre nom et votre prénom.
  5. Eteignez votre serveur Jetty, car notre application Scala va utiliser le même port 8080

Mise en route de l’application : bienvenue dans le monde de SBT

SBT est l’outil de build “standard” que l’on utilise avec Scala. Sa principale force est de proposer une compilation incrémentale, ce qui permet de gagner beaucoup de temps : en effet, Scala est particulièrement lent à compiler, ce qui rend l’utilisation de Maven assez pénible.

Avec SBT on arrive ainsi à un processus de build acceptable, par contre c’est au détriment de tout le reste : les plugins SBT sont pour beaucoup buggés, mal documentés, et utilisent souvent de vieilles librairies. C’est pour cette raison que notre application va utiliser une vieille version de Jetty, avec uniquement la spécification Servlet 2.5, alors que notre objectif initial était d’utiliser TomEE et les spécifications CDI et Servlet 3.0.

Je trouve particulièrement dommage qu’un langage nous impose d’utiliser un outil de build, qui lui-même nous impose d’utiliser une vieille version de serveur d’application. Il y a là un signe sur l’état de la communauté Scala aujourd’hui : il y a peu de gens utilisant un serveur d’application Java EE avec Scala, la plupart préférant sans doute Akka/Play!

Pour pouvoir construire notre projet :

  1. Clonez notre repository https://github.com/ippontech/primefaces-scala-cassandra
  2. Installez SBT https://github.com/harrah/xsbt/wiki
  3. Lancez SBT et tapez : “container:start”
  4. L’application doit être disponible sur http://127.0.0.1:8080

Quelques astuces d’utilisation de SBT :

  1. Pour avoir un redéployement à chaud de l’application, tapez : “~;container:start; container:reload /”
  2. Pour pouvoir utiliser votre application dans IDEA, tapez : “gen-idea”

Bien entendu, je vous conseille fortement d’utiliser les plugins proposés sous Eclipse et IDEA afin de pouvoir faire du Scala.

Utilisation de Scala avec PrimeFaces

L’utilisation de classes Scala dans PrimeFaces est particulièrement simple. La classe User ne fait que quelques lignes :


(Code d’origine disponible ici)

C’est une “case class”: ce type de classe exporte automatiquement les paramètres de son constructeur, et génère automatiquement les méthodes equals() et toString(), ce qui facilite son écriture. De plus, cette classe utilise les annotations @BeanProperty afin de générer automatiquement les getters/setters correspondant à ces paramètres. Nous pouvons donc coder une classe extrêmement concise et lisible. Afin de pouvoir accéder à cette classe en JSF, nous avons besoin d’un ManagedBean, c’est-à-dire d’un Bean géré par JSF :

(Code d’origine disponible ici)

Cette classe est également extrêmement simple :

  • L’annotation @ManagedBean transforme automatiquement cette classe en composant géré par JSF (notez que dans le fichier web.xml le package de cette classe est scanné par JSF)
  • Elle utilise également le système des @BeanProperty pour générer des getters/setters
  • Attention cependant, cette classe n’utilise pas les collections Scala, qui ne sont pas compatibles avec les collections Java : nous renvoyons donc une collection Java, qui est le seul type d’objet que peut utiliser PrimeFaces

Cette classe sera par la suite utilisée normalement dans notre page JSF, disponible ici.

Utilisation de Scala avec Cassandra

Malheureusement, les drivers Cassandra disponibles en Scala ne sont pas de très bonne qualité :

  • Cassie, utilisé et développé par Twitter, semble le plus prometteur : malheureusement, à l’heure actuelle, le package n’est pas utilisable car il manque des dépendances. De plus, il n’est même pas listé dans la liste des drivers de Cassandra
  • Cascal est actuellement le plus abouti, mais son auteur d’origine a abandonné le projet

Cependant, cela n’est pas très important : Scala permet d’utiliser sans problème des librairies Java “normales”, il n’est donc pas nécessaire d’utiliser des librairies spécifiques à Scala.

J’ai donc simplement utilisé l’excellente librairie Hector que nous utilisons également sur Tatami, ce qui a fonctionné sans problème.

Voici le code d’accès à Cassandra, afin de lire l’ensemble des utilisateurs de la Column Family “User” :

(Code d’origine disponible ici)

Cette classe est intéressante à plusieurs niveaux :

  • Le code d’Hector est généralement assez complexe à utiliser car il utilise beaucoup les generics : Scala typant automatiquement les objets, il est nettement plus simple d’écrire “val rows” que d’écrire “List<Row> rows” ! Là encore, nous avons gagné beaucoup de temps à écrire ce code.
  • Cette classe est en fait un “object” Scala, ce qui en fait automatiquement un singleton. Pas la peine de faire des méthodes static (qui n’existent pas en Scala, d’ailleurs), ou d’utiliser un framework IoC pour gérer ses singletons. Pour des cas simples comme le nôtre, cela nous facilite donc grandement la vie. Pour des cas plus compliqués, où l’on aura par exemple besoin d’AOP, il faudra alors utiliser un framework comme Spring, qui d’ailleurs fonctionne parfaitement avec Scala (voir par exemple https://github.com/ewolff/scala-spring )
  • Elle utilise le nouveau langage CQL proposé dans les dernières versions de Cassandra, ce qui permet d’avoir un code simple et assez proche d’une base de données classique, ce qui facilite grandement son utilisation par rapport à l’API Hector “classique”

En conclusion

Même si le code proposé ici semble très simple, sa mise en place et son développement ont été assez coûteux. Les différents plugins Scala ne sont pas toujours très stables, le langage est très différent de Java : si on compare cette expérience à du code Groovy, par exemple, Scala a une courbe d’apprentissage beaucoup plus élevée et une communauté nettement moins mature.

Cependant, cette expérience est particulièrement positive sur deux points :

  • L’application finale fonctionne très bien
  • Le code est effectivement beaucoup plus concis que du code Java

Scala peut donc permettre de coder des applications Java EE de manière plus rapide, et surtout plus lisible, à partir du moment où l’on passe la barrière de la courbe d’apprentissage, laquelle est tout de même assez rédibitoire en termes de coût.

Tweet about this on TwitterShare on FacebookGoogle+Share on LinkedIn

7 réflexions au sujet de « Utilisation de Scala pour simplifier une application PrimeFaces + Cassandra »

  1. Pardon, mais dans ton exemple, la complexité et le cout de la courbe d’apprentissage seraient plus dus à Casasndra, et à son model plutôt complexe, puis à la forêt d’annotations issues de Java EE, qu’au langage Scala lui même. Apprendre à utiliser une case class, puis quelques controles de langages, ne me paraissent pas si compliqués. Ou alors dans ce cas inutile d’apprendre tout autre langage différent de Java.

    1. – Je suis d’accord sur le fait que Cassandra peut être complexe, encore que dans l’exemple j’ai justement utilisé du CQL, ce qui ne doit pas être difficile à appréhender pour un développeur qui fait du SQL. De manière générale, ce qui est compliqué dans Cassandra ce n’est pas le développement, c’est la bonne gestion de son cluster, ce qui est un tout autre problème.
      – Par contre pour la partie Java EE je ne suis pas d’accord : d’une part nous n’utilisons qu’une seule annotation Java EE (le ManagedBean), et d’autre part il s’agit là d’un standard que tout développeur est sensé connaître. Je comprends qu’on critique Java EE (je ne suis pas le dernier à critiquer d’ailleurs), par contre on est obligé de connaitre, c’est quand même la base de notre métier. Et puis dans le cas présent, cette annotation m’a quand même permis d’avoir automatiquement mon tableau HTML, sans presque rien coder, et là franchement je ne connais pas mieux pour faire une interface Web.
      – Enfin pour la complexité de Scala : je connais pas mal de langages et j’en ai rarement vu un aussi compliqué, à part du Perl parfois… Si on compare à Groovy, comme je le faisais dans ma conclusion, cela m’a paru beaucoup plus difficile : en Groovy je pouvais coder des trucs sympa au bout d’une heure à peine, alors qu’en Scala il m’a clairement fallu plus de temps. Cela a aussi beaucoup été dû à SBT, qui m’a fait perdre beaucoup de temps : l’outillage est encore un autre sujet, mais là également je n’ai pas été épaté par ce qui était proposé, par rapport à ce à quoi on a désormais l’habitude dans les autres langages.

  2. Ce genre de techno (JSF en l’occurence) ne fait pas honneur à Scala qui est utilisé ici uniquement comme une syntaxe différente pour Java.
    On ne voit pas du tout l’aspect programmation fonctionnelle dans cet exemple. Le fait de devoir utiliser une ArrayList Java (mutable) est assez anti-naturel pour un développeur Scala par exemple.
    Je pense que la principale difficulté quand on commence Scala est de se mettre à l’aise avec les concepts fonctionnels et de sortir du schéma de pensée impératif Java. C’est à ce moment là que la puissance et l’élégance de Scala sautent aux yeux.
    Note : pour l’AOP (comme pour l’injection de dépendance) nul besoin de framework, le langage gère très bien ça de lui même

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


*