====== Play! framework (old page) ====== The Playframework makes it easier to build Web applications with Java.\\ Finally a Java framework made by Web developers. Discover a clean alternative to bloated enterprise Java stacks. Play focuses on developer productivity and targets RESTful architectures. C'est Symfony pour Java ! Ce framework n'est pas basé sur J2EE, il embarque directement sont serveur ([[http://www.jboss.org/netty|Netty]]). [[http://www.playframework.org/]] **Discussions**: * [[http://www.developpez.net/forums/f1462/java/developpement-web-java/frameworks/autres/play/|forum developpez.net]] * [[https://groups.google.com/group/play-framework/topics|Google groupes]] * [[http://stackoverflow.com/questions/tagged/playframework|stackOverflow]] * [[http://maps.google.com/maps/ms?ie=UTF8&oe=UTF8&msa=0&msid=207454583624912240450.0004990d22aafc925bbb7&ll=39.53794,-2.438965&spn=9.756751,21.643066&z=6|Google map des players]] **=> [[informatique:java:frameworks:play_framework:play_1.2_bugs]]** ===== Tutos & Articles ===== Recherche des [[http://www.google.fr/search?hl=fr&ie=UTF-8&q=Play+Framework&lr=&tbm=blg|dernières publications sur Play! avec Google]]. * [[http://www.slideshare.net/sim51/formation-play-framework|Slides de présentation]] en français * [[http://linsolas.developpez.com/articles/java/play/guide/|Développer une application avec le framework Play !]]. Traduction française du tutoriel officiel de Play Framework visant à créer un moteur de blog (26/01/2010). * Articles sur la [[http://www.playframework.org/community/planet|Planet ♥ Play]] * Les articles de [[http://www.lunatech-research.com/users/peter-hilton|Peter Hilton]] et tous ceux de [[http://www.lunatech-research.com/editorials|Lunatech research]] * [[http://www.zengularity.com/item/1985200523/introduction-aux-webservices-rest-avec-play|Introduction aux webservices REST avec Play!]] : requêtes REST, sélection du fomat html,xml et json par configuration. * Exposer une API REST/XML avec Play! : [[http://coffeebean.loicdescotte.com/2010/05/exposer-sur-api-restxml-avec-play.html|part 1]], [[http://coffeebean.loicdescotte.com/2010/05/exposer-une-api-restxml-avec-play.html|part 2]] * [[http://www.objectify.be/wordpress/?p=163|Rethink: i18n in play]] * [[http://www.lunatech-research.com/playframework-file-upload-blob#filename|Play framework file upload with play.db.jpa.Blob]] **Code snippets**: * [[http://www.playframework.org/community/snippets|Code snippets]]: You can submit your code snippets here, to share patterns with the community. **Play! Framework cheat sheets**: * [[http://www.crionics.com/public/play-contrib/TheUltimatePlayCheatSheet.pdf|The Ultimate PlayCheatSheet]] (revision 2011-01-02) * [[http://playcheatsheet.appspot.com/show/ArtemMedeu/armed/play-cheatsheets|Play! Framework cheat sheet]] * [[http://download.playframework.org/miscellaneous/play-cheat-sheet.pdf|PlayFramework 1.0.2.1 cheat sheet]] **Maturité ?** * I don't know for other sites but the playframework website was built with play and serve about 100.000 request by day. * playframework.org that run on Play 1.1.1 has server 245,923 requests in february without any downtime or errors, and still consume 11Mo of heap. Of course the application itself is very simple but it proves that the framework stack including the HTTP server, has no problems nor memory leaks. * [[http://stackoverflow.com/questions/2646681/play-framework-real-world-production-experiences|Play Framework: Real-world production experiences ?]] * Sites: [[http://www.mairie2424.fr/]] et [[http://www.mairie2424.fr/nos-references-collectivites.html|ses références]], [[http://57hao.com/]], [[http://www.masterbranch.com/]], [[http://www.trendiction.de/]], [[http://www.quora.com/]], [[http://www.beansight.com/]] **Manque de doc pour:** * Ecrire un Plugin ? * The Play plug-in is the class that provides access to the Play framework's extension points. [[http://www.playframework.org/documentation/api/1.2/play/PlayPlugin.html|PlayPlugin Javadoc]] * [[http://stackoverflow.com/questions/4699250/how-to-extend-the-playframework|How to extend the playframework ?]] * [[http://www.lunatech-research.com/archives/2011/01/11/declarative-model-class-enhancement-play|Declarative model class enhancement in Play]] * Ecrire un Module ? * [[http://stackoverflow.com/questions/4120424/how-does-one-creates-a-play-module|How does one creates a Play Module ?]] * [[http://playframework.wordpress.com/2011/02/27/play-modules/|Play Modules]] * [[http://www.objectify.be/wordpress/?p=135|Sharing a domain model between two Play! apps]] **Divers**: > ... And, **with the bytecode vodoo it is doing** (injecting code at runtime) ... >> There is no more vodoo things than in any other web framework. For example typical Spring applications do a lot more of magical things at runtime (including dynamic proxy, runtime members injection and AOP generation). In Play there is nothing really resolved at runtime. Everything, including bytecode manipulation, is done at compilation time, and either it works or it fails at compilation time, ie. at start time in production mode. ===== Tips ===== [[http://www.playframework.org/community/snippets|Code snippets]]: You can submit your code snippets here, to share patterns with the community. unescape #{get 'var' /} #{set var:'this is " a test'.raw() /} Configurer Netbeans pour qu'il trouve les sources du Play framework: In Netbeans: Right click on your project -> Properties -> Java Sources Classpath -> Add Jar/Folder... -> Select the folder /framework/src [[http://stackoverflow.com/questions/4699180/how-to-get-the-anchor-of-url-in-plays-controller/|How to get the anchor of url in play's controller]] Modifier la génération d'application et autre tâches: voir autour de play-framework/resources/application-skel/conf/application.conf the **@{}** syntax is meant to generate relative URLs while the **@@{}** syntax generates absolute ones. \\ Take a look at the documentation additional details: [[http://www.playframework.org/documentation/1.2/templates#Actionsor|Actions: @{…} or @@{…}]] > What does the percentage sign specify in application.conf ? >> It’s a way to define settings according to a given environment. >> When you write **“%id.property=value”** the “id” refers to a Play! id. >> This line will be considered only if you run your application using Play! with id “id”. >> See [[http://www.playframework.org/documentation/1.2/ids]] for more information. ===== Templating / Views ===== Ajouter des styles depuis une vue: #{set 'moreStyles'} #{/set} et dans le layout: ... #{get 'moreStyles' /} ... ** Ajax DataTables ** [[http://www.lunatech-research.com/archives/2011/02/07/ajax-datatables-playframework|Ajax DataTables with the Play framework]]: This article is a follow-on to [[http://www.lunatech-research.com/archives/2011/01/28/playframework-jquery-datatables|Integrating Play framework with jQuery DataTables]], which describes how to integrate [[http://www.datatables.net/|DataTables (jQuery plugin)]] with a Play framework web application. This time, we show how to load the table data from the server using Ajax, rather than decorating an existing (populated) HTML table. ==== Modules ==== [[https://github.com/schaloner/tabula-rasa|Tabula Rasa]]: Tabula Rasa provides support for user-customisable tables, allowing each user to have a custom view of any table in your application. Client-side support is provided using the excellent [[http://www.datatables.net/|DataTables jQuery plugin]]. ===== Template Engines ===== ==== Japid ==== [[http://www.playframework.org/modules/japid]] * [[https://github.com/branaway/Japid]] * [[https://github.com/branaway/Japid/wiki/Japid-User-Guide|The Japid User Manual]] * [[https://github.com/branaway/Japid/wiki/server-side-include-with-japid|Server Side Include with Japid]] * [[https://github.com/branaway/Japid/wiki/Porting-ZenContact-to-Japid|Porting to Japid]] * [[https://github.com/branaway/playclipse|The Japid Plugin for Eclipse]] ==== Cambridge ==== [[http://code.google.com/p/cambridge|cambridge]] Un moteur de template pour remplacer celui de Play!. * [[http://blog.erdincyilmazel.com/2011/02/10/comparing-cambridge-template-engine-with-jsp-velocity-freemarker-and-play-framework-templates/|Comparing Cambridge Template Engine with Jsp, Velocity, Freemarker and Play Framework Templates]] * [[http://code.google.com/p/cambridge/wiki/TemplateAuthorsGuide|Template Authors Guide]] * [[http://code.google.com/p/cambridge/wiki/UsingWithPlayFramework|Using With Play Framework]] ==== Google Closure ==== [[http://www.playframework.org/modules/googleclosure]] This module is aimed at integrating Google Closure tools with play!. For the time being, it ONLY provides **javascript client templating** based on [[http://code.google.com/intl/fr-FR/closure/templates/|Google Closure Templates]]. ===== Tests ===== * [[http://www.devinprogress.info/2011/03/unit-test-your-play-controllers.html|Unit test your Play! controllers]] * [[http://www.devinprogress.info/2011/04/how-play-framework-test-runner-works.html|How the play framework test runner works]] * Test Module: The play!framework [[https://github.com/GuyMograbi/play_test_module]] will help you write better tests for play!framework applications. ==== Fetching the response body ==== > In a functional test that uses GET to fetch a JSON response, how does one get the JSON result from the response body? > I have the following in my test: > Http.Response response = GET(request, "/whatever"); > assertIsOk(response); > assertContentType("application/json", response); > I know I can use assertContentEquals and assertContentMatch to make assertions about what's in the response body, but how do I fetch that response body itself? > The Http.Response class doesn't seem to have any appropriate method. >> You can use getContent(response) to extract the response content as String ===== Models & Data stuff ===== Binding uploaded Excel to application models, the lazy way (ExcelBinder): [[http://www.objectify.be/wordpress/?p=186|Part 1]], [[http://www.objectify.be/wordpress/?p=204|Part 2]] [[http://groups.google.com/group/play-framework/browse_thread/thread/55c992148879171d|Using persistence out of a Play app]] [[http://www.playframework.org/community/snippets/5|Keep track of record creation/updates]]: gestion des champs "created_at" et "updated_at" par héritage de classe pour les modèles. ==== JPA / Hibernate ==== When using bidirectional relationships in JPA, maintaining consistency between both sides of the relationship for in-memory objects is up to you. \\ See [[http://stackoverflow.com/questions/4674896/when-is-onetomany-list-populated-in-play-framework|When is @OneToMany list populated in Play framework ?]] [[http://stackoverflow.com/questions/912659/what-is-the-proper-way-to-re-attach-detached-objects-in-hibernate|What is the proper way to re-attach detached objects in Hibernate ?]] === Configuration JPA / Hibernate === # Dans conf/application.conf # # Pour voir toutes les requêtes SQL: jpa.debugSQL=true # ou hibernate.show_sql=true # # Hibernate will generate comments inside the SQL, for easier debugging: hibernate.use_sql_comment=true # # statics gathering: hibernate.generate_statistics=true # ### Do not use this, it's bring many problems ! ### quote all database identifiers (Hibernate 3.5+) ## hibernate.globally_quoted_identifiers=true === Bug: counting composite key === La requête SQL générée pour compter des Entity avec une Composite Identity est mal formée: /* select count(e) from models.CategoryCombinaisonItem e */ select top ? count((categoryco0_."categoryValueId", categoryco0_."categoryId", categoryco0_."categoryCombinaisonId")) as col_0_0_ from "CategoryCombinaisonItem" categoryco0_ La fonction count() ne prend qu'une seule colonne ! En rapport: * Play community : [[https://github.com/playframework/play/pull/55]], [[http://play.lighthouseapp.com/projects/57987-play-framework/tickets/479]] * Hibernate community: [[http://opensource.atlassian.com/projects/hibernate/browse/HHH-4044]], [[http://seamframework.org/Community/CompositeKeyMysqlEntityQueryBrokenInSeam212]] **It's a Play! bug** : * CategoryCombinaisonItem.count() throw the Exception * CategoryCombinaisonItem.count("") not ! J'ai ouvert le ticket [[http://play.lighthouseapp.com/projects/57987-play-framework/tickets/717|#717]]. === JPQL "In List" parameter Binding === Je n'arrive pas à Binder un tableau en parameter in(?) du Query JPA int[] existingValuesId2 ; CategoryValue.delete("category.id = ? and id not in (?)", category.id, //existingValuesId ); // ClassCastException occured : java.util.ArrayList cannot be cast to java.lang.Integer //Arrays.asList(existingValuesId) ); // IllegalArgumentException occured : Parameter value [[7]] was not matching type [java.lang.Integer] //existingValuesId.toArray() ); // ClassCastException occured : [Ljava.lang.Object; cannot be cast to java.lang.Integer //existingValuesId2 ); // (Integer[]) ClassCastException occured : [Ljava.lang.Integer; cannot be cast to java.lang.Integer //existingValuesId2 ); // (int[]) ClassCastException occured : [I cannot be cast to [Ljava.lang.Object; // Obligé de faire une concaténation !!! String existingValuesIdString = ""; for (int i = 0; i < existingValuesId.size(); i++) { existingValuesIdString += (i>0?",":"") + existingValuesId.get(i); } CategoryValue.delete("category.id = ? and id not in (" + existingValuesIdString + ")", category.id); **The solution :** List idExs; Exponent.find( "id in (:ids)" ) .bind( "ids", idExs ) .fetch(); ==== Modules ==== [[https://github.com/sim51/logisima-play-yml|logisima-play-yml]]: Module to generate yml file from your database ===== Localisation / Internationalisation ===== ==== Modules ==== === Messages module === [[http://www.playframework.org/modules/messages]] Module messages provides a web based tool for managing your application’s localizations. * Forgetting the localizations as you code? This tool will look through your sources and lists the keys that have not been localized yet! * Forgot to remove the localizations when you refactoring? It also finds keys that are no longer in use and let’s you easily remove them! * Your messages file is a mess? The messages files are saved in alphabetical order so you can easily add keys to the files manually too! * Not sure where the key is used? No worries, the tool will show you a snippet from the source code where it found the key! ===== Conception / Architecture ===== [[http://www.lunatech-research.com/archives/2011/01/11/declarative-model-class-enhancement-play|Declarative model class enhancement in Play]]: Explain how the @CrudName annotation works (play.classloading.enhancers.Enhancer, play.PlayPlugin). **Page composition / Composite View**: il est fréquent pour un site web que les pages soient composées de plusieurs controller/view, par exemple les dernières news à droite, les derniers commits en bas, ... Dans Symphony (Php), Tapestry, Wicket, c'est possible. Avec Play! Il n'est pas prévu (et donc déconseillé) de composer une vue à partir de plusieurs controller.\\ Voir: [[http://groups.google.com/group/play-framework/browse_thread/thread/22d1ad0adeb15b08/3d08d705f86f35cc|invoking other controller actions from template (page composition)]], [[https://groups.google.com/group/play-framework/browse_thread/thread/3240d7d3eedbf25d|Using #{include tag to include non-static elements]] \\ **Update** 2011-03-02: \\ > We'll introduce a very similar concept in a next version of Play (not the 1.2 since I want to release it this month).\\ > You mean that controller action will only be called from http and the componentes would only be called from the views? \\ > Yes. **Héritage de Controller**. [[http://groups.google.com/group/play-framework/browse_thread/thread/ce64bcadbddc0f32|Contoller.parent() is @Deprecated]], [[http://groups.google.com/group/play-framework/browse_thread/thread/c477fc6ae0dd3be3|What to use instead of parent()?]]. With the current implementation of the Controller layer in Play, controllers inheritance is a bad practice, the controller layer is not object oriented in Play. Well, I'd said that the only usage of controller inheritance (apart extending the Controller class) is to share code between classes. Using inheritance for that is an anti-pattern in general (not only in Play, but in every OO languages). ==== Appels asynchrones et Jobs ==== **Long query**: > Don't forget that the threading model of Play is not the same than a servlet container. You don't need too much database connections for a Play application since it uses a fixed (and generally very low) amount of threads to execute the requests. > Basically if your applications uses 3 threads, then 3 database connections are enough. >> Sure the thread model is better, but if I serve 5 user per second, and the request takes 6 seconds in database access, with only three connections users must wait for free connections. >>> If your DB-Queries take 6 seconds, you should probably think of **doing them in a job and use suspendable request** feature of play. [[http://www.playframework.org/community/snippets/10|How can I keep track of a job progress ?]] [[http://blog.matthieuguillermin.fr/2011/03/appels-asynchrones-avec-play-framework/|Appels asynchrones avec Play Framework]]: Démonstration d'une classe qui va permettre d’"écouter" les modifications et de "notifier" les abonnés lorsqu’une modification a lieu. Le [[http://playjobs.mashup.fm/@jobs|Jobs Status]] de //felipera// ([[http://groups.google.com/group/play-framework/browse_thread/thread/d0619b0c720290d7/f475be5f1ffc0674|googlegroup post]]). ===== Securité ===== ==== Cross Site Request Forgery (CSRF) ==== Play génère automatiquement un token qu'il mets dans les forms générées avec le tag #{form} ... Mais il ne vérifie pas ce token automatiquement ! Il faut le faire explicitement. Il faut lire cet article pour appréhender toute la porter de la protection CSRF à implémenter avec Play : [[http://www.lunatech-research.com/archives/2011/02/22/play-framework-security-fighting-cross-site-request-forgery|Play Framework Security: Fighting Cross Site Request Forgery]] ===== Control d'accès ===== **User's role**: If each user only has a single role, then the **Secure module** is what you need. I can't really add more than what's detailed in [[http://www.playframework.org/documentation/1.1.1/secure]] and [[http://www.playframework.org/documentation/1.1.1/guide8]] - these cover everything you need, and the example code of yabe can be used as a guide. If each user can have more than one role, consider the **deadbolt module** this allows you to and, or and not role combinations in your security restrictions. ==== deadbolt module ==== > How can I implement multiple user roles in Play!, with each having role-specific permissions and views, and what would be an appropriated database scheme? >> Use the deadbolt module ! > I've just released Deadbolt 1.3 in order to provide arbitrary security on named resources at the method, class or view level. You can now have resources which are entirely locked by the RestrictedResource annotation, or allow a fallback to the static authorisation of Restrict and Restrictions. @With(Deadbolt.class) public class MyController extends Controller { @RestrictedResource(name="foo") public static void list() { // depending } @RestrictedResource(name="bar", staticFallback=true) @Restrict("cheese") public static void delete() { } } > Determining access is done via RestrictedResourcesHandler instances which are provided to Deadbolt via the DeadboltHandler. This means you can have various types of RestrictedResourcesHandlers based on, again, arbitrary decisions. ==== Autres modules ==== CAS authentification module (SSO): * [[https://github.com/sim51/logisima-play-cas#readme]] ===== Performance ===== ==== Press ==== The press module is a JavaScript and CSS minimizer that is designed to be transparent to the application developer: Simply replace