déc 27

Dans cet article, je vais vous montrer comment créer une application Play! et comment la déployer sur Google AppEngine.

Google AppEngine (GAE) propose une solution d’hébergement d’applications gratuites très pratiques pour des applications Java. La liste des fonctionnalités offertes par GAE peut-être consultée ici.
Le framework Play! fournit un module extrêmement bien fait pour déployer des applications sur Gae et un autre module est disponible pour gérer le Datastore Gae : Siena.


Powered by Google App Engine

Google AppEngine

Google fournit un SDK complet pour développer des applications destinées à être hébergées par GAE. Dans le cas d’une application Play!, ce SDK est intégré au module GAE et le SDK n’est nécessaire que pour le déploiement final.
Il faut récupérer ce SDK à cette adresse : http://code.google.com/appengine/downloads.html.
La version Windows nécessite d’installer aussi Python (un lien est fourni via l’installeur du SDK).

Attaquons-nous à la partie applicative de cet article !

Play! Framework

Tout d’abord, il faut installer les modules GAE et Siena de Play! :

play install gae
play install siena

Une fois ces installations terminées, créons notre future application test-gae

play new test-gae

Enrichissons le conf/application.conf nouvellement créé avec les 2 modules précédents :

# ---- MODULES ----
module.gae=${play.path}/modules/gae-1.4
module.siena=${play.path}/modules/siena-1.3

Le Modèle

GAE sans stocker des données dans le Datastore, ça ne sert pas à grand chose.
Nous allons donc créer un objet modèle très simple que l’on retrouve dans quasiment toutes les applications : User !

package models;

import java.util.List;
import siena.Column;
import siena.Generator;
import siena.Id;
import siena.Max;
import siena.Model;
import siena.NotNull;
import siena.Query;

public class User extends Model {
	
    @Id(Generator.AUTO_INCREMENT)
    public Long id;

    @Column("login")
    @Max(15) @NotNull
    public String login;
	
    @Column("nickname")
    @Max(15) @NotNull
    public String nickname;
    ...
    ...
}

Il y a plusieurs choses importantes à noter :

  • La classe User étend la classe siena.Model et non plus la classe play.Model du framework Play!.
    Logique : play.Model est destiné à JPA qui n’est pas utilisé par GAE.
  • Il faut mettre un Id ! L’annotation @Id est obligatoire et elle doit pointer sur une variable de type Long nommée id.
  • Les autres annotations sont optionnelles. Par défaut, la table créée prendra le nom de la classe et les colonnes prendront le nom des variables sur lesquelles elles pointent.

Il va maintenant falloir ajouter des méthodes à notre modèle afin de pouvoir récupérer des données :

...
static Query<User> all() {
    return Model.all(User.class);
}
	
public static List<User> findAll() {
    return all().fetch();
}
    
public static User findById(Long id) {
    return all().filter("id", id).get();
}
    
public static User findByLogin(String login) {
    return all().filter("login", login).get();
}

Nous avons ajouté une méthode protected all() qui créé une Query qui ramènera tous les Users.
A partir de cette méthode, nous allons appliquer différents filtres pour ramener les données qui nous intéressent :

  • fetch() pour ramener toutes les données d’une Query.
  • filter(“id”, id).get() pour filtrer les données dont l’attribut id est égal à id.
  • filter(“login”, login).get() pour filtrer les données dont l’attribut login est égal à login.

Nous avons maintenant un petit modèle. Attaquons-nous au contrôleur dédié à User !

Le Contrôleur

Pour faire le plus simple possible, utilisons le contrôleur créé par défaut par Play! : Application.

package controllers;

import java.util.List;

import models.User;
import play.mvc.Controller;

public class Application extends Controller {

    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }

    public static void add(String login, String nickname) {
        User add = new User();
        add.login = login;
        add.nickname = nickname;
        add.insert();

        index();
    }

    public static void delete(Long id) {
        notFoundIfNull(id);
        User toRemove = User.findById(id);
        toRemove.delete();

        index();
    }
}

Il s’agit d’un contrôleur tout ce qu’il y a de plus classique en Play!.
Une des méthodes va ramener la liste des Users, une autre va permettre d’en ajouter un et enfin la dernière permet d’en supprimer un.

Notre contrôleur est prêt, ajoutons-lui une page html pour pouvoir jouer avec !

La Vue

Contentons-nous d’utiliser le fichier index.html du contrôleur Application :

#{extends 'main.html' /}
#{set title:'Home' /}

<p>
<h2>Liste des Users :</h2>
  #{list items:users, as:'user'}
    <div><label>[${user.id}] ${user.login} (${user.nickname})</label><label>#{a @Application.delete(user.id)}Delete#{/a}</label></div>
  #{/list}
</p>

<p>
#{form @Application.add()}
<h2>Add a User :</h2>
<div>
  <label>Login :</label>
  <input type="text" name="login" />
</div>

<div>
  <label>Nickname :</label>
  <input type="text" name="nickname" />
</div>
<div>
  <input type="submit" value="Add" />
</div>
#{/form}
</p>

Rien que du très classique Play! : une liste pour afficher tous les Users, un lien pour supprimer un User et enfin un formulaire pour créer un User.

Notre application est désormais prête à être déployée sur Google AppEngine !
Vous pouvez la tester avec un play run, elle devrait tourner parfaitement.

Le déploiement sur Google AppEngine

Lorsque nous avons créé l’application avec un play new test-gae, le module GAE a créé un répertoire war à la racine de notre application.
Celui-ci contient un fichier généré automatiquement : web.xml.
Il va être important de le modifier pour pouvoir déployer correctement sur GAE.

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application><!-- ID GAE de votre application --></application>
  <version>1</version>
</appengine-web-app>

La balise application doit contenir l’ID de votre application Google AppEengine.
Pour le déterminer, il faut créer une application dans Google AppEngine.

Créer une application dans Google AppEngine

Rendez-vous sur https://appengine.google.com/.
Vous devez vous identifier avec votre compte Gmail.
Lors de la création de votre première application, il vous demandera sûrement un numéro de téléphone portable pour vous envoyer un code.
Une fois cette étape passée, vous devriez pouvoir créer une application Google AppEngine :

C’est le champ Application Identifier qui contient l’id de votre application à mettre dans votre fichier web.xml.

Hop, votre application a dûe être déclarée dans Google AppEngine !

Déployer l’application sur Google AppEngine

Ma petite soeur peut le faire : en se plaçant dans le répertoire de notre application, il suffit de lancer :

play gae:deploy --gae={path_to_gae_sdk}

path_to_gae_sdk indique votre installation du SDK Google AppEngine.

Vous devriez voir Play! précompiler les classes, assembler un war puis tenter d’uploader votre application.
Il vous demanderas sûrement votre login et mot de passe Gmail pour vous identifier sur votre compte.
Une fois l’upload terminé, vous pouvez administrer votre application grâce à la console AppEngine :
https://appengine.google.com

Votre application est disponible à l’url indiquée par la console d’administration :

Voici l’archive du projet, prête à l’emploi : Zip.

3 Responses to “Une application Play! sur Google AppEngine”

  1. [...] Ce billet était mentionné sur Twitter par nicogiard. nicogiard a dit: RT @jpbriend: Débuter avec Play! et Google AppEngine: http://bit.ly/h2n45w #playframework #gae [...]

  2. Nicolas dit :

    Merci.
    J’ai suivi a peu près les même étapes.
    Mon appli est productive sur GAE.

    Je cherche maintenant à faire évoluer mon modèle, exemple ici en ajoutant un champ à la classe User, mais Siena se plaint de ne pouvoir charger les éléments null.

    Avez-vous déja fait évoluer votre modèle de données?

  3. Je pense que tu as 2 solutions :
    - faire un update sur tes entités déjà existantes (par code ou par la console GAE).
    - gérer de façon programmatique le fait que certains de tes instances sont en version v1 et donc pas ‘completes’.

    Ca dépend de ton modèle : le NoSQL est très pratique pour gérer des versions différentes d’objets mais les mises à jour d’objets existants doivent être gérées manuellement.

Leave a Reply


Creative Commons License
Blog Infin-It par Infin-It est mis à disposition selon les termes de la licence Creative Commons Paternité-Pas d'Utilisation Commerciale 2.0 France.