PLAY FRAMEWORK
« JAVA IS FUN AGAIN »
Toulouse JUG – 17 novembre 2011
Le programme
   L’histoirede Play!
   Développer avec Play!
   Test, déploiement, exploitation

   L’écosystème autour de Play!

   Le futur

   Alors, Play ou pas Play?
A propos…
    Sylvain Wallez
       Architecteexpert freelance, web & Java
       2008-2010 : CTO de Goojet/Scoop.it
       2006-2008 : Backend architect Joost
       2000-2008 : cofondateur & CTO
        Anyware Technologies
       2003 : premier VP français de la fondation
        Apache
       Membre du Tetalab, hacking Kinect & Arduino


                 sylvain@bluxte.net
                 http://bluxte.net
                 Twitter: @bluxte
L’histoire de Play
C’est quoi, c’est qui, d’où ça vient ?
L’histoire de Play
    Framework web
       Orienté    REST (urls matter !)
    Framework full stack
       http,   persistance, build, test, déploiement
    Haute productivité
       TrèsDRY
       Save / reload, recompilation à la volée



    Très inspiré de Rails et Django !            J2EE
L’histoire de Play
  Créé par Guillaume Bort (cocorico !) de Zenexity
  Open source en 2008

  Licence Apache

  Actuellement : version 1.2.3 (Java + Scala)

  Bientôt : version 2.0 (Scala + Java)
L’histoire de Play
    Les frameworks web Java sont créés par des devs
     Java, et pas des développeurs web

    Java a une culture de la complexité, préférant
     l’empilement des abstractions à la résolution
     effective des problèmes

    Mais l’écosystème Java est incroyablement riche
Développer avec Play!
Hello world… et un peu plus
L’appli finale… wow!
Création du projet
Le contrôleur

            package controllers;	
            	
            import play.data.validation.Required;	                  Méthode
            import play.mvc.Controller;	
            	
                                                                    statique
Appel du    public class Application extends Controller {	
            	
template        public static void index() {	
                    render();	
                }	
            	
                public static void hello(@Required String who) {	
            	                                                       Binding et
                    if (validation.hasErrors()) {	                  validation
 Template               render("@index");	
                    } else {	
  nommé                 render(who);	
                    }	
                }	
            }	


                                                 Modèle
                                                pour la vue
Les vues
                             index.html
  Héritage de                                              Variables
                #{set title:'Bienvenue' /}	
   template     #{extends 'main.html' /}	
                	
                <form action="@{Application.hello}"	
                       method="POST">	                     Reverse
                	                                          routing
                  <p>Dire bonjour à	
                    <input name="who"/> #{error 'who'/}	
                  </p>	
                  <p>	
                    <input type="submit"/>	
                  </p>	
                </form>	
                                                           Validation

                              hello.html
                #{set title:'Bonjour' /}	
                #{extends 'main.html' /}	
    Modèle      	
                <h1>Bonjour ${who} !</h1>	
                	
                <p>	
                  <a href="@{Application.index}">	
                     Recommencer	
                  </a>	
                </p>
Les vues

                                          main.html
             <!DOCTYPE html>	
             <html>	
                 <head>	
                      <title>${title}</title>	
                      <meta charset="${_response_encoding}">	                          CSS
                      <link rel="stylesheet" media="screen”	                        spécifiques
                            href="@{'/public/stylesheets/main.css'}">	
             	
                                                                                     à la vue
                      #{get 'moreStyles' /}	
             	
                      <link rel="shortcut icon" type="image/png”	
                            href="@{'/public/images/favicon.png'}">	
                      <script src="@{'/public/javascripts/jquery-1.5.2.min.js'}”	
                              type="text/javascript"></script>	
             	
 Inclusion            #{get 'moreScripts' /}	
de la vue    	
                 </head>	
                 <body>	
             	
                      #{doLayout /}	
             	
                 </body>	
             </html>
Lancement du serveur
L’architecture de Play!
Mais comment ça marche ?
Architecture de Play
    Modèle MVC classique…

                      HTTP
                                 Routes           DB
                     server




                     Views     Controllers     Models



     … mais une implémentation iconoclaste !
Architecture : le serveur
    Serveur HTTP : ce n’est pas du Servlet !
       Serveur NIO très léger et rapide (Netty)
       Pas de session (stateless, scalabilité horizontale)



    Besoin stateful ? API cache avec EHCache &
     Memcache fournie


                                                HTTP
                                                          Routes         DB
                                               server




                                               Views    Controllers   Models
Architecture : routage des URLs
       Routes : dispatching des requêtes sur les contrôleurs
           Tout le REST est là
Méthode                                                                               Contrôleur
 HTTP        # Home page	
             GET     /                                     Application.index	
             	
             # Ignore favicon requests	
             GET     /favicon.ico                          404	
             	
             # Map static resources from the /app/public folder to the /public path	
             GET     /public/                              staticDir:public	
             	
             # Catch all	
             *       /{controller}/{action}                {controller}.{action}	




                                                                     HTTP
                                                                                Routes             DB
                                                                    server
             Pattern


                                                                    Views     Controllers    Models
Architecture : routage des URLs
              GET    /                                      Application.index	
              	
              GET    /public/                               staticDir:public	
 « mount »    GET    /imgcache/                             staticDir:imgcache	
d’un module   	
              *      /admin                                 module:crud	
              	
              GET    /villes/{name}                         Villes.showByName	
                                                                                               URLs
              GET    /boutiques/{name}                      Boutiques.showByName	         « SEO friendly »
              GET    /categories/{name}                     Categories.showByName	
              GET    /villes/{id1}/categorie/{id2}          Villes.categorie	
              GET    /{controller}/{name},{id}              {controller}.show2	
              	
              	
              POST   /{action}                              Application.{action}_post	
              GET    /{action}                              Application.{action}	
              	
              GET    /{controller}/                         {controller}.index	
              POST   /{controller}/                         {controller}.index_post	
              	
              POST   /{controller}/-{id1}/{action}/-{id2}   {controller}.{action}_post	
              GET    /{controller}/-{id1}/{action}/-{id2}   {controller}.{action}	
                                                                                             Patterns
              	                                                                             génériques
              GET    /{controller}/-{id}                    {controller}.show	
              	
              POST   /{controller}/-{id}/{action}           {controller}.{action}_post	
              GET    /{controller}/-{id}/{action}           {controller}.{action}	
              	
              POST   /{controller}/{action}                 {controller}.{action}_post	
              GET    /{controller}/{action}                 {controller}.{action}
Architecture : contrôleurs
    Contrôleurs : méthodes statiques
       Un contrôleur est sans état
       Binding et validation automatique des paramètres

       request/response ? Pas besoin 90% du temps !




                                            HTTP
                                                      Routes         DB
                                           server




                                           Views    Controllers   Models
Architecture : contrôleur
    Paramètres de la vue : bytecode analysis pour
     extraire les variables locales
       Finis   les model.addAttribute("user",                  user)    !

                     public static void hello(@Required String who) {	
                 	
                          if (validation.hasErrors()) {	
                              render("@index");	
                          } else {	
                              render(who);	
                          }	
                     }
Architecture : modèles
    Modèles
       Attributs    publics
         Ecriture
                 simplifiée : user.getName()  user.name !
         Bytecode processing : génération des getter/setter

       DAO   : méthodes statiques


    Fin du « anemic domain model »

                                                 HTTP
                                                           Routes         DB
                                                server




                                                Views    Controllers   Models
Architecture : modèles
             package models;	
             	
             import ...	
Entité JPA   	
             @Entity	
             public class UserGroup extends Model {	
             	
                 @Required	
                 public String name;	
             	
                 @Required	
                 public String accessCode;	
             	
                 @ManyToOne	
get/set          public User coach;	
             	
générés          public long getSize() {	
                      return find("select count(u) from User u where u.group = ?", this).first();	
                 }	
             	
                 // DAO methods	
             	
                 public static UserGroup findByAccessCode(String code) {	
                      return find("accessCode", code).first();	
                 }	
  DAO        	
                 public static List<UserGroup> findByCoach(User user) {	
                      return find("select g from UserGroup g where g.isActivated = true" +	
                         	           	" and g.coach = ?", user).fetch();	
                 }	
             }
Architecture : vues
    Vues : templates Groovy
       Héritage de templates
       Nombreux tags : structures de contrôle, forms, erreurs
        de validation, tables, etc.
         Un   tag est un mini template
       Escaping   HTML par défaut !
    Autres moteurs via des modules
       Scalate,   Japid, Cambridge…
                                              HTTP
                                                        Routes         DB
                                             server




                                             Views    Controllers   Models
Architecture : vues
              <p>	
                  #{if product.ratingCount != 0}	
                    <div class="rateit" data-rateit-value="${product.rating}"></div>	
                    <a href="#">Notez ce produit</a>	
                  #{/if}	
                  #{else}	
                    <div class="rateit"></div>	
                    <a href="#">Soyez le premier à noter ce produit.</a>	
                  #{/else}	
              </p>	
              	
 Iteration            	
                      	
              #{list results, as: 'product'}	
                <p class="clear">	
                  <img src="${product.thumbnailUrl}" style="float: left"/>	
                  ${product.link}<br/>	
                  Boutique ${product.shop.link} à ${product.shop.city.link}.	
                </p>	
              #{/list}	
              	
              <div class="${page.cssClass}">	
                <h1>${page.title}</h1>	
                ${page.text.textile()}	
              </div>	
              	
 Fonctions
d’extension
Les tests avec Play!
Ah bon, faut tester ?
Les tests
    Junit, Corbertura et Selenium intégrés
       Avec   des « helpers » spécialisés
           public class ApplicationTest extends FunctionalTest {	
           	
               @Test	
               public void testThatIndexPageWorks() {	
                   Response response = GET("/");	
                   assertIsOk(response);	
                   assertContentType("text/html", response);	
                   assertCharset(play.Play.defaultWebEncoding, response);	
               }	
           }	




           #{selenium}	
               // Open the home page, and check that no error occured	
               open('/')	
               assertNotTitle('Application error')	
           #{/selenium}
Les tests
    « play test »
Les tests
Déploiement, opérations
Quand le code est fini, c’est là que tout
commence !
Déploiement
    The Play! Way
       Pull   du code (taggué) et « play start »
         Tout   est précompilé au démarrage


    The J2EE way
       « play    war » crée un war
         Permet   de s’intégrer dans un environnement J2EE
Configuration
    Fichier de properties centralisé
          # i18n	
          # ~~~~~	
          # Define locales used by your application.	
          # You can then place localized messages in conf/messages.{locale} files	
          	
          # Date format	
          # ~~~~~	
          # date.format.fr=dd/MM/yyyy	
          	
          # Server configuration	
          # ~~~~~	
          # If you need to change the HTTP port, uncomment this (default is set to 9000)	
          # http.port=9000	
          #	
          # By default the server listen for HTTP on the wilcard address.	
          # You can restrict this.	
          # http.address=127.0.0.1	
          # Session configuration	
          # ~~~~~~~~~~~~~~~~~~~~~~	
          # By default, session will be written to the transient PLAY_SESSION cookie.	
          # The cookies are not secured by default, only set it to true	
          # if you're serving your pages through https.	
          # application.session.cookie=PLAY	
          # application.session.maxAge=1h	
          # application.session.secure=false	
          	
          # JVM configuration	
          # ~~~~~	
          # Define which port is used by JPDA when application is in debug mode (default is
          set to 8000)	
          # jpda.port=8000	
          #
Configuration
        Modes dev/integration/prod, etc
                # JPA Configuration (Hibernate)	
                # ~~~~~	
                #	
                # Specify the custom JPA dialect to use here (default to guess):	
                # jpa.dialect=org.hibernate.dialect.PostgreSQLDialect	
                #	
                # Specify the ddl generation pattern to use. Set to none to disable it 	
  Config        # (default to update in DEV mode, and none in PROD mode):	
                # jpa.ddl=update	
  de tests      	
                %test.application.mode=dev	
                %test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0	
                %test.jpa.ddl=create	
                %test.mail.smtp=mock	
                	
   Config       %integration.db=mysql://root@localhost/helloworld	
                %integration.jpa.ddl=none	
d’intégration
Monitoring
    « play status »
Monitoring
    Disponible en texte et en JSON
       Intégration        très simple avec munin, collectd, etc.
    Librairie JaMon pour du monitoring applicatif facile

            Monitor monitor = MonitorFactory.start("SuperAlgorithm.findTheAnswer");	
                    	
            // Do complicated stuff	
            // (should be 42 anyway...)	
                    	
            monitor.stop();	




     Monitors:	
     ~~~~~~~~	
     SuperAlgorithm.findTheAnswer, ms.   ->   1 hits;   1038,0 avg;   1038,0 min;   1038,0 max;
L’écosystème Play!
On peut être full-stack et être accueillant !
L’écosystème
    Des modules à foison
       Systèmede plugins qui apportent composants, tags,
       templates, moteurs de persistance, générateurs de
       PDF/Excel, interfaces mobiles, etc…
    Play a son repository de modules
       Gestion  des dépendances avec Ivy
       Intégration avec tout repository Maven
L’écosystème : dépendances Ivy

          require:	
              - play	
Modules       - play -> fbgraph 0.3 :	
                    transitive : false	
 Play         - play -> secure	                                                 Dépendances
          	                                                                     Maven Central
              - com.restfb -> restfb 1.6.9	
              - org.codehaus.jackson -> jackson-core-asl 1.8.0	
              - org.codehaus.jackson -> jackson-mapper-asl 1.8.0	
              - org.apache.lucene -> lucene-core 3.3.0	
              - org.apache.lucene -> lucene-spatial 3.3.0	
              - com.hazelcast -> hazelcast 1.9.4 :	
                  exclude:	
                      - org.mockito -> *	                                         Repository
          	
              - local-lib -> json-lib 2.4-jdk15	                                     local
          	
          repositories:	
              - local-lib:	
                  type: local	
                  artifact: "${application.path}/local/lib/[module]-[revision].jar"	
                  contains:	
                      - local-lib -> *
Le futur de Play!
Scala en douceur
Le futur de Play
    Play 2.0 beta sorti hier (16 nov)
       Moteur en Scala / Akka
       API Java pour « masquer » Scala

       Templates Scala avec typage fort
       Performances extrèmes
Le futur de Play
    TypeSafe s’engage sur Play 2.0
       La société du créateur de Scala
       Play pourrait bien être la « killer app » qui fait
        décoller Scala
       L’API Java permet une évolution en douceur vers Scala
Le futur de Play
    Play 1.x is dead ?
       Non, beaucoup de projets existants
       Mais entrée en mode maintenance



    Play 2.0 est compatible avec Play 1.x ?
       Lesprincipes sont les mêmes, mais les APIs changent
       Adaptation importante nécessaire
Play ou pas Play ?
Alors, on joue ou pas ?
The good
  Oubliez J2EE, (re)découvrez la simplicité
  Fin des getters et setters !

  Beaucoup moins de code

  Reload / recompil automatique

  Des messages d’erreurs parlants

  Développement high-speed et « in the flow »
The bad
    Byte code processing
       Le   debugger n’aime pas (re-attach à chaque recompil)
        Mais   on en a aussi moins besoin !
    Méthodes statiques
       Empêche    l’héritage sur les contrôleurs
        Des   « contournements » existent dans la lib Play
    Bonne doc, mais code source peu commenté
The ugly




           (void)
The ugly



               Ah si…
       le temps nécessaire pour
         convaincre votre DSI
    (mais chuuut… « play war » et hop !)
Quand choisir Play ?
  Une application web
  Adhérence sur la couche métier acceptable

       Ou   se passer de l’intégration Play dans le modèle
  Avec des développeurs calés en HTML,
   mais pas forcément experts en Java
  Quand vous êtes pressé

  Projet court/moyen terme avec Play 1.x
Merci !



          Questions ?

          Réponses !

Play Framework - Toulouse JUG - nov 2011

  • 1.
    PLAY FRAMEWORK « JAVA ISFUN AGAIN » Toulouse JUG – 17 novembre 2011
  • 2.
    Le programme  L’histoirede Play!   Développer avec Play!   Test, déploiement, exploitation   L’écosystème autour de Play!   Le futur   Alors, Play ou pas Play?
  • 3.
    A propos…   Sylvain Wallez   Architecteexpert freelance, web & Java   2008-2010 : CTO de Goojet/Scoop.it   2006-2008 : Backend architect Joost   2000-2008 : cofondateur & CTO Anyware Technologies   2003 : premier VP français de la fondation Apache   Membre du Tetalab, hacking Kinect & Arduino sylvain@bluxte.net http://bluxte.net Twitter: @bluxte
  • 4.
    L’histoire de Play C’estquoi, c’est qui, d’où ça vient ?
  • 5.
    L’histoire de Play   Framework web   Orienté REST (urls matter !)   Framework full stack   http, persistance, build, test, déploiement   Haute productivité   TrèsDRY   Save / reload, recompilation à la volée   Très inspiré de Rails et Django ! J2EE
  • 6.
    L’histoire de Play  Créé par Guillaume Bort (cocorico !) de Zenexity   Open source en 2008   Licence Apache   Actuellement : version 1.2.3 (Java + Scala)   Bientôt : version 2.0 (Scala + Java)
  • 7.
    L’histoire de Play   Les frameworks web Java sont créés par des devs Java, et pas des développeurs web   Java a une culture de la complexité, préférant l’empilement des abstractions à la résolution effective des problèmes   Mais l’écosystème Java est incroyablement riche
  • 8.
    Développer avec Play! Helloworld… et un peu plus
  • 9.
  • 10.
  • 11.
    Le contrôleur package controllers; import play.data.validation.Required; Méthode import play.mvc.Controller; statique Appel du public class Application extends Controller { template public static void index() { render(); } public static void hello(@Required String who) { Binding et if (validation.hasErrors()) { validation Template render("@index"); } else { nommé render(who); } } } Modèle pour la vue
  • 12.
    Les vues index.html Héritage de Variables #{set title:'Bienvenue' /} template #{extends 'main.html' /} <form action="@{Application.hello}" method="POST"> Reverse routing <p>Dire bonjour à <input name="who"/> #{error 'who'/} </p> <p> <input type="submit"/> </p> </form> Validation hello.html #{set title:'Bonjour' /} #{extends 'main.html' /} Modèle <h1>Bonjour ${who} !</h1> <p> <a href="@{Application.index}"> Recommencer </a> </p>
  • 13.
    Les vues main.html <!DOCTYPE html> <html> <head> <title>${title}</title> <meta charset="${_response_encoding}"> CSS <link rel="stylesheet" media="screen” spécifiques href="@{'/public/stylesheets/main.css'}"> à la vue #{get 'moreStyles' /} <link rel="shortcut icon" type="image/png” href="@{'/public/images/favicon.png'}"> <script src="@{'/public/javascripts/jquery-1.5.2.min.js'}” type="text/javascript"></script> Inclusion #{get 'moreScripts' /} de la vue </head> <body> #{doLayout /} </body> </html>
  • 14.
  • 15.
    L’architecture de Play! Maiscomment ça marche ?
  • 16.
    Architecture de Play   Modèle MVC classique… HTTP Routes DB server Views Controllers Models … mais une implémentation iconoclaste !
  • 17.
    Architecture : leserveur   Serveur HTTP : ce n’est pas du Servlet !   Serveur NIO très léger et rapide (Netty)   Pas de session (stateless, scalabilité horizontale)   Besoin stateful ? API cache avec EHCache & Memcache fournie HTTP Routes DB server Views Controllers Models
  • 18.
    Architecture : routagedes URLs   Routes : dispatching des requêtes sur les contrôleurs  Tout le REST est là Méthode Contrôleur HTTP # Home page GET / Application.index # Ignore favicon requests GET /favicon.ico 404 # Map static resources from the /app/public folder to the /public path GET /public/ staticDir:public # Catch all * /{controller}/{action} {controller}.{action} HTTP Routes DB server Pattern Views Controllers Models
  • 19.
    Architecture : routagedes URLs GET / Application.index GET /public/ staticDir:public « mount » GET /imgcache/ staticDir:imgcache d’un module * /admin module:crud GET /villes/{name} Villes.showByName URLs GET /boutiques/{name} Boutiques.showByName « SEO friendly » GET /categories/{name} Categories.showByName GET /villes/{id1}/categorie/{id2} Villes.categorie GET /{controller}/{name},{id} {controller}.show2 POST /{action} Application.{action}_post GET /{action} Application.{action} GET /{controller}/ {controller}.index POST /{controller}/ {controller}.index_post POST /{controller}/-{id1}/{action}/-{id2} {controller}.{action}_post GET /{controller}/-{id1}/{action}/-{id2} {controller}.{action} Patterns génériques GET /{controller}/-{id} {controller}.show POST /{controller}/-{id}/{action} {controller}.{action}_post GET /{controller}/-{id}/{action} {controller}.{action} POST /{controller}/{action} {controller}.{action}_post GET /{controller}/{action} {controller}.{action}
  • 20.
    Architecture : contrôleurs   Contrôleurs : méthodes statiques   Un contrôleur est sans état   Binding et validation automatique des paramètres   request/response ? Pas besoin 90% du temps ! HTTP Routes DB server Views Controllers Models
  • 21.
    Architecture : contrôleur   Paramètres de la vue : bytecode analysis pour extraire les variables locales   Finis les model.addAttribute("user", user) ! public static void hello(@Required String who) { if (validation.hasErrors()) { render("@index"); } else { render(who); } }
  • 22.
    Architecture : modèles   Modèles   Attributs publics   Ecriture simplifiée : user.getName()  user.name !   Bytecode processing : génération des getter/setter   DAO : méthodes statiques   Fin du « anemic domain model » HTTP Routes DB server Views Controllers Models
  • 23.
    Architecture : modèles package models; import ... Entité JPA @Entity public class UserGroup extends Model { @Required public String name; @Required public String accessCode; @ManyToOne get/set public User coach; générés public long getSize() { return find("select count(u) from User u where u.group = ?", this).first(); } // DAO methods public static UserGroup findByAccessCode(String code) { return find("accessCode", code).first(); } DAO public static List<UserGroup> findByCoach(User user) { return find("select g from UserGroup g where g.isActivated = true" + " and g.coach = ?", user).fetch(); } }
  • 24.
    Architecture : vues   Vues : templates Groovy   Héritage de templates   Nombreux tags : structures de contrôle, forms, erreurs de validation, tables, etc.   Un tag est un mini template   Escaping HTML par défaut !   Autres moteurs via des modules   Scalate, Japid, Cambridge… HTTP Routes DB server Views Controllers Models
  • 25.
    Architecture : vues <p> #{if product.ratingCount != 0} <div class="rateit" data-rateit-value="${product.rating}"></div> <a href="#">Notez ce produit</a> #{/if} #{else} <div class="rateit"></div> <a href="#">Soyez le premier à noter ce produit.</a> #{/else} </p> Iteration #{list results, as: 'product'} <p class="clear"> <img src="${product.thumbnailUrl}" style="float: left"/> ${product.link}<br/> Boutique ${product.shop.link} à ${product.shop.city.link}. </p> #{/list} <div class="${page.cssClass}"> <h1>${page.title}</h1> ${page.text.textile()} </div> Fonctions d’extension
  • 26.
    Les tests avecPlay! Ah bon, faut tester ?
  • 27.
    Les tests   Junit, Corbertura et Selenium intégrés   Avec des « helpers » spécialisés public class ApplicationTest extends FunctionalTest { @Test public void testThatIndexPageWorks() { Response response = GET("/"); assertIsOk(response); assertContentType("text/html", response); assertCharset(play.Play.defaultWebEncoding, response); } } #{selenium} // Open the home page, and check that no error occured open('/') assertNotTitle('Application error') #{/selenium}
  • 28.
    Les tests   « play test »
  • 29.
  • 30.
    Déploiement, opérations Quand lecode est fini, c’est là que tout commence !
  • 31.
    Déploiement   The Play! Way   Pull du code (taggué) et « play start »  Tout est précompilé au démarrage   The J2EE way   « play war » crée un war  Permet de s’intégrer dans un environnement J2EE
  • 32.
    Configuration   Fichier de properties centralisé # i18n # ~~~~~ # Define locales used by your application. # You can then place localized messages in conf/messages.{locale} files # Date format # ~~~~~ # date.format.fr=dd/MM/yyyy # Server configuration # ~~~~~ # If you need to change the HTTP port, uncomment this (default is set to 9000) # http.port=9000 # # By default the server listen for HTTP on the wilcard address. # You can restrict this. # http.address=127.0.0.1 # Session configuration # ~~~~~~~~~~~~~~~~~~~~~~ # By default, session will be written to the transient PLAY_SESSION cookie. # The cookies are not secured by default, only set it to true # if you're serving your pages through https. # application.session.cookie=PLAY # application.session.maxAge=1h # application.session.secure=false # JVM configuration # ~~~~~ # Define which port is used by JPDA when application is in debug mode (default is set to 8000) # jpda.port=8000 #
  • 33.
    Configuration   Modes dev/integration/prod, etc # JPA Configuration (Hibernate) # ~~~~~ # # Specify the custom JPA dialect to use here (default to guess): # jpa.dialect=org.hibernate.dialect.PostgreSQLDialect # # Specify the ddl generation pattern to use. Set to none to disable it Config # (default to update in DEV mode, and none in PROD mode): # jpa.ddl=update de tests %test.application.mode=dev %test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0 %test.jpa.ddl=create %test.mail.smtp=mock Config %integration.db=mysql://root@localhost/helloworld %integration.jpa.ddl=none d’intégration
  • 34.
    Monitoring   « play status »
  • 35.
    Monitoring   Disponible en texte et en JSON   Intégration très simple avec munin, collectd, etc.   Librairie JaMon pour du monitoring applicatif facile Monitor monitor = MonitorFactory.start("SuperAlgorithm.findTheAnswer"); // Do complicated stuff // (should be 42 anyway...) monitor.stop(); Monitors: ~~~~~~~~ SuperAlgorithm.findTheAnswer, ms. -> 1 hits; 1038,0 avg; 1038,0 min; 1038,0 max;
  • 36.
    L’écosystème Play! On peutêtre full-stack et être accueillant !
  • 37.
    L’écosystème   Des modules à foison   Systèmede plugins qui apportent composants, tags, templates, moteurs de persistance, générateurs de PDF/Excel, interfaces mobiles, etc…   Play a son repository de modules   Gestion des dépendances avec Ivy   Intégration avec tout repository Maven
  • 38.
    L’écosystème : dépendancesIvy require: - play Modules - play -> fbgraph 0.3 : transitive : false Play - play -> secure Dépendances Maven Central - com.restfb -> restfb 1.6.9 - org.codehaus.jackson -> jackson-core-asl 1.8.0 - org.codehaus.jackson -> jackson-mapper-asl 1.8.0 - org.apache.lucene -> lucene-core 3.3.0 - org.apache.lucene -> lucene-spatial 3.3.0 - com.hazelcast -> hazelcast 1.9.4 : exclude: - org.mockito -> * Repository - local-lib -> json-lib 2.4-jdk15 local repositories: - local-lib: type: local artifact: "${application.path}/local/lib/[module]-[revision].jar" contains: - local-lib -> *
  • 39.
    Le futur dePlay! Scala en douceur
  • 40.
    Le futur dePlay   Play 2.0 beta sorti hier (16 nov)   Moteur en Scala / Akka   API Java pour « masquer » Scala   Templates Scala avec typage fort   Performances extrèmes
  • 41.
    Le futur dePlay   TypeSafe s’engage sur Play 2.0   La société du créateur de Scala   Play pourrait bien être la « killer app » qui fait décoller Scala   L’API Java permet une évolution en douceur vers Scala
  • 42.
    Le futur dePlay   Play 1.x is dead ?   Non, beaucoup de projets existants   Mais entrée en mode maintenance   Play 2.0 est compatible avec Play 1.x ?   Lesprincipes sont les mêmes, mais les APIs changent   Adaptation importante nécessaire
  • 43.
    Play ou pasPlay ? Alors, on joue ou pas ?
  • 44.
    The good   OubliezJ2EE, (re)découvrez la simplicité   Fin des getters et setters !   Beaucoup moins de code   Reload / recompil automatique   Des messages d’erreurs parlants   Développement high-speed et « in the flow »
  • 45.
    The bad   Byte code processing   Le debugger n’aime pas (re-attach à chaque recompil)  Mais on en a aussi moins besoin !   Méthodes statiques   Empêche l’héritage sur les contrôleurs  Des « contournements » existent dans la lib Play   Bonne doc, mais code source peu commenté
  • 46.
    The ugly (void)
  • 47.
    The ugly Ah si… le temps nécessaire pour convaincre votre DSI (mais chuuut… « play war » et hop !)
  • 48.
    Quand choisir Play?   Une application web   Adhérence sur la couche métier acceptable   Ou se passer de l’intégration Play dans le modèle   Avec des développeurs calés en HTML, mais pas forcément experts en Java   Quand vous êtes pressé   Projet court/moyen terme avec Play 1.x
  • 49.
    Merci ! Questions ? Réponses !