Autour du codeDevelopper toujours mieux
Posté le

Play le framework java inspiré de Django

Aujourd'hui, j'ai voulu tester play pour me faire une idée et voir jusqu'où deux framework basés sur des technologies différentes peuvent ou pas se ressembler.

Prise en main

Play est aussi simple à prendre en main que Djando. À l'instar de Django, un script permet de créer ses applications.

$ ./activator new my-app play-java

est l'équivalent de

$ ./django-admin.py startapp my-app

Notez cependant qu'il existe une version graphique pour play.

Une fois dans notre application, un script activator nous permet de lancer la console. La première fois c'est très long le temps de télécharger toutes les jars. La gestion des dépendances se fait avec le fichier build.sbt. C'est comme le fichier requirements.txt lorsque vous utilisez Pip sous Python. Tout comme Django, play intègre un serveur de développement, donc pas de prise de tête avec tomcat ou glassfish. Le site en dev est directement accessible sur le port 9000. Les fichiers modifiés sont rechargés à chaud et les erreurs de compilation ou de routage apparaissent dans votre navigateur.

La console permet également de créer les fichier de configuration pour pouvoir utiliser votre IDE favori comme Eclipse ou autre pour développer votre application.

On va enfin pouvoir entrer dans le vif du sujet. La première différence majeure entre les deux framework est l'architecture play c'est du MVC alors que Django du MVT.

Les Controleurs

Les Controleurs sont des classes qui étendent play.mvc.Controller. Ils sont composés d'Action, ce sont des méthodes qui retourne un play.mvc.Result en utilisant request. C'est l'équivalent des views en Django. Le routage des actions est fait par le fichier texte /conf/routes qui par la suite est transformé en classe java. C'est l'équivalent de l'url.py.

Exemple de controleur:

package controllers;

import play.*;
import play.mvc.*;
import play.mvc.Http.*;
import views.html.*;
import models.*;
import play.data.Form;
import java.util.List;

public class Application extends Controller {
    /** Action qui affiche la liste de mes clients */
    public static Result list_user() {
        List<Customer> customers = Customer.find.all(); // Requête
        return ok(views.html.Application.list_user.render(customers));
    }
    ... d'autre actions
}

GET      /list_user              controllers.Application.list_user()
POST     /save_user              controllers.Application.save_user()
GET      /add_user               controllers.Application.add_user()

La différence et qu'avec Django les vues gèrent elles-mêmes si elles s'occupent de requête POST, GET ou autres. Dans play c'est déclaré dans le fichier routes et une même action ne peut pas recevoir une route pour GET et une route pour POST.

Les Models

Coté ORM, c'est moins intégré que dans Django. Vous avez le choix entre Hibernate ou Ebean. Je me suis tourné vers Ebean. Contrairement à Hibernate, Ebean ne respecte pas la JPA (Java Persistance API) et utilise des annotations, il n'y a pas de fichier de mapping à écrire.

Le modèle possède une méthode save et les requête peuvent être fait via l'objet Finder.

package models;

import java.util.Date;
import javax.persistence.*;
import play.db.ebean.*;
import play.data.format.*;
import play.data.validation.Constraints;

@Entity
public class Customer extends Model {

    @Id
    @GeneratedValue
    public long id;

    @Constraints.Required
    public String first_name;

    @Constraints.Required
    public String last_name;

    @Formats.DateTime(pattern="dd/MM/yyyy")
    public Date birthday_date = new Date();

    public static Finder<Long,Customer> find = new Finder<Long,Customer>(
        Long.class, Customer.class
    );
}

exemple de requête:

Customer customer = Customer.find.byId(32);
List<Customer> customers = Customer.find.all()
List<Customer> customers = Customer.find.where().eq("name", "Dupond").findList();

Les Vues

Pour ce qui est du moteur de template, il est basé sur Scala. Les variables qui seront utilisées dans vos templates doivent être déclarées au début. Ensuite, chaque template est transformé en fonction Scala puis compilé en Bytecode java.

@(customers: List[Customer])

<h1>Customer list</h1>
<ul>
@for(customer <- customers) {
  <li>@customer.first_name @customer.last_name</li>
}
</ul>
<a href="@{routes.Application.add_user}">Add customer</a>

Les forms

Comme avec django, les formulaires peuvent être généré à partir du modèle et être instancier à partir d'une requête POST. un get() permet de récupérer une instance du modèle et un save sur cette instance l'incrustera en BDD.

Exemple d'utilisation de form dans mon contrôleur

public class Application extends Controller {

    public static Result list_user() {
        List<Customer> customers = Customer.find.all();
        return ok(views.html.Application.list_user.render(customers));
    }

    public static Result add_user() {
        Form<Customer> CustomerForm = Form.form(Customer.class);
        return ok(views.html.Application.add_user.render(CustomerForm));
    }

    public static Result save_user() {
        Form<Customer> CustomerForm = Form.form(Customer.class).bindFromRequest();
        if(CustomerForm.hasErrors()) {
           return ok(views.html.Application.add_user.render(CustomerForm));
        } else {
            Customer newCustomer = CustomerForm.get();
            newCustomer.save();
            return ok(views.html.Application.save_user.render(newCustomer));
        }
    }
}

Conclusion

Le peu que j'ai testé de Play m'a fait très bonne impression. L'apprentissage est rapide plus qu'en Django me semble t-il. par contre, je pense que la réutilisabilité des applications est moins efficace et cela est dû à la liberté laissé par Play sur le choix de l'ORM. Il n'y a pas non plus d'équivalent au Django CBV dans play qui permet un développement Dry est rapide. Néanmoins, play reste un framwork que je vous recommande d'essayer et sur lequel je pense m'attarder un peu plus.