dimanche 25 décembre 2011

Premiers pas avec Scalatra

Scalatra est un framework Web ultra léger pour le langage Scala inspiré par Sinatra, un framework très populaire dans le monde Ruby.


Scalatra privilégie une approche très simple basée sur les principes REST. Pour effectuer une action, on part d'une méthode HTTP et d'une route (URL d'accès à la fonction), auxquelles on ajoute le traitement désiré :
get("/hello") {
    "hello!"
}

Avec cette approche et la manipulation XML proposée en Scala, on peut déclarer et renvoyer du contenu comme ceci :
get("/hello") {
  <html>
      <body>
        <h1>Hello!</h1>
     </body>
   </html>
}
On peut facilement ajouter des paramètres dans l'URL :
get("/hello/:name") { 
    <html>
      <body>
        <h1>Hello {params("name")} !</h1>
      </body>
    </html>
  }
Renvoyer du contenu XML (ou JSON ou ce qu'on veut) pour exposer un service REST :
get("/persons"){
 contentType="application/xml"
 <xml>
     <persons>{
         Database.entries.map { 
                    entry =>  <person>{entry}</person> 
                }
     }</persons>
 </xml> 
 }
Faire un POST pour enregistrer de nouvelles données :
post("/person"){
 val name = params("name")
 Database.addEntry(name)
 redirect("/persons")
  }
Remarque : Pour tester la méthode ci-dessus, on peut par exemple utiliser curl en ligne de commande :
curl for test: curl --data "name=jim" http://localhost:8080/person

On peut aussi rediriger l'action vers un template :
 get("/hello2/:name") {
      templateEngine.layout("hello-scalate.scaml", Map("name" -> params("name")))
  }
Scalatra est livré par défaut avec le moteur de template Scalate, qui est compatible avec plusieurs formats de templates. Voici un exemple avec le format scaml :
//redefinition du titre dans le layout par défaut
- attributes("title") 
//paramètre de requête
-@ val name: String

%h1 Welcome!
%p Hello, how are you #{name} ?
Enfin, on peut définir les actions à effecter en cas d'erreur :
notFound { 
<h1>Nothing found here</h1>
<img src="/images/404.jpg" />        
}
Le framework fonctionne avec l'outil de build SBT. Un support des WebSockets est proposé à travers la librairie Socket.IO. En utilisant Jetty, le conteneur par défaut de Scalatra, on peut recharger le code à chaud (plus ou moins rapidement). Pour cela on le démarre avec la commande suivante :
 sbt
 > container:start
   > ~ aux-compile
Dans cet exemple, j'ai simulé à la base de données avec un "object" Scala. Un object est l'équivalent d'un singleton : c'est une classe qui possède une instance unique.
object Database{
 //shared entries (simulate database)
 var entries = List("bob", "joe", "john") 
 def addEntry(name: String){
     entries = entries:+name
 }
}
On pourra facilement remplacer cette implémentation par une vraie base de données. Si vous n'avez pas besoin d'une base SQL (ce qui est en fait souvent le cas), vous pouvez regarder des choses plus simples comme la base de données objet NeoDatis qui supporte officiellement Scala. Pour des besoins de scalabilité plus importants, vous pouvez aussi jeter un oeil du côté de MongoDB et de Casbah (son toolkit Scala). Avec ce genre d'outils vous conserverez une architecture simple, pas besoin de s'embêter avec des frameworks à la Spring, le langage apporte tout ce qu'il faut pour gérer l'injection de dépendance nativement. Pour conclure, Scalatra nous prouve que contrairement aux idées reçues, on peut faire des choses extrêmement simples et efficaces en Scala avec des API bien pensées. Si vous cherchez quelque chose s'en rapprochant et utilisant le langage Java, vous pouvez regarder du côté de Spark.
Et puis j'allais oublier, joyeux Noël à tous!

Site officiel de Scalatra