Table des matières

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 (Netty).

http://www.playframework.org/

Discussions:

play_1.2_bugs

Tutos & Articles

Recherche des dernières publications sur Play! avec Google.

Code snippets:

Play! Framework cheat sheets:

Maturité ?

Manque de doc pour:

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

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 <play source code base>/framework/src

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: 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'}
 <link rel="stylesheet" type="text/css" media="screen" href="@{'/public/stylesheets/xxx.css'}" />
#{/set}

et dans le layout:

<head>
 ...
 #{get 'moreStyles' /}
 ...

Ajax DataTables

Ajax DataTables with the Play framework: This article is a follow-on to Integrating Play framework with jQuery DataTables, which describes how to integrate 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

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 DataTables jQuery plugin.

Template Engines

Japid

http://www.playframework.org/modules/japid

Cambridge

cambridge

Un moteur de template pour remplacer celui de Play!.

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 Google Closure Templates.

Tests

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): Part 1, Part 2

Using persistence out of a Play app

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 When is @OneToMany list populated in Play framework ?

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:

It's a Play! bug :

J'ai ouvert le ticket #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<Integer> idExs;
Exponent.find( "id in (:ids)" )
 .bind( "ids", idExs )
 .fetch();

Modules

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.

Conception / Architecture

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: invoking other controller actions from template (page composition), 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. Contoller.parent() is @Deprecated, 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.

How can I keep track of a job progress ?

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 Jobs Status de felipera (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 : 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):

Performance

Press

The press module is a JavaScript and CSS minimizer that is designed to be transparent to the application developer: Simply replace <script> tags with #{press.script} tags, and <link rel=“stylesheet”> tags with #{press.stylesheet} tags.

greenscript

http://www.playframework.org/modules/greenscript, http://github.com/greenlaw110/greenscript

Minimize javascript/css files [greenscript] module:

Déploiement

Deploy and running Play! without the source code ?
Use the 'precompile' command. Then you could deploy the application without the app/ folder.
Serving several apps
Play applications usually run on a dedicated VM. You can generate WAR files and deploy them into a classical JEE application servers, but it's not optimal. For me running 50 JVM on a server with 16GB of RAM is ok. — Guillaume Bort 28/02/2011
Amazon EC2
I'm using a micro EC2 instance to run Play! website with few traffic. I'm using nginx and PostgreSQL in the same micro instance, and all works ok.
The only problem is when you start the Play! application in production mode. Because, when Play! start to compile all classes and views, the instance becomes to be very unstable due to high load CPU (if you see the documentation about how works an EC2 micro instance, you will understand this point better). To avoid this, you can precompile the application locally, upload precompiled/ directory to EC2 instance, and start the application with -Dprecomplied=true.

Start/Stop script

start: "play start" - this will run play in background and put a pid file in the current folder
stop: "play stop" - this will get the pid file and stop the play process and then remove the pid file