h1. Controllers

Business logic is managed in the domain model layer. As a client (typically a web browser) cannot directly invoke this code, the functionality of a domain object is exposed as resources represented by URIs.

A client uses the uniform API provided by the HTTP protocol to manipulate these resources, and by implication the underlying business logic. However, this mapping of resources to domain objects is not a bijection: the granularity can be expressed at different levels, some resources may be virtual, for some resources aliases may be defined…

This is precisely the role played by the Controller layer: providing a **glue** between the domain model objects and transport layer events. As the Model layer, controllers are written in pure Java, making it easy to access or modify Model objects. Like the HTTP interface, Controllers are procedural and Request/Response oriented.

The Controller layer reduces the **impedance mismatch** between HTTP and the Domain Model.

p(note). **Note**
 
There are different architectural models with different strategies. Some protocols give you direct access to the domain model objects. This is typically what EJB or Corba protocols do. In these cases, the architectural style used is RPC (Remote Procedure Call). These communication styles are hardly compatible with web architecture.
 
Some technologies like SOAP try to give access to the model object domain through the Web. However, SOAP is just another RPC-style protocol, in this case using HTTP as a transport protocol. It is not an application protocol.

The web’s principles are not fundamentally object-oriented. So a layer is needed to adapt HTTP to your favorite language. 


h2. <a name="overview">Controller overview</a>

A Controller is a Java class, hosted by the @controllers@ package, and subclassing @play.mvc.Controller@.

This is a Controller:

bc. package controllers;
 
import models.Client;
import play.mvc.Controller;
 
public class Clients extends Controller {
 
    public static void show(Long id) {
        Client client = Client.findById(id);
        render(client);
    }
     
    public void delete(Long id) {
        Client client = Client.findById(id);
        client.delete();
    }
 
}

Each public method in a Controller is called an action. In case an action method is not static, a new instance of the controller class is created for each request, and all controller methods are invoked on the same instance. This works only if the controller has a zero-argument constructor (or no constructors at all).

The signature for an action method is:

bc. public void static action_name(params...);

or 

bc. public void action_name(params...);

You can define parameters in the action method signature. These parameters will be automatically resolved by the framework from the corresponding HTTP parameters.

Usually, an action method doesn’t include a return statement. The method exit is done by the invocation of a **result** method. In this example, @render(…)@ is a result method that executes and displays a template.

h2. Static or non-static?

In the past, all controller methods had to be static. However, non-static methods have many advantages in Java:

* They can be overridden in subclasses.
* They are easier to mock/unit-test.
* They allow storing of request-scoped state in controller fields, if needed.

Having that said, both static and non-static controller methods are supported.

h2. <a name="params">Retrieving HTTP parameters</a>

An HTTP request contains data. This data can be extracted from:

* The URI path: in @/clients/1541@, 1541 is the dynamic part of the URI Pattern.
* The Query String: @/clients?id=1541@.
* The request body: if the request was sent from an HTML form, the request body contains the form data encoded as @x-www-urlform-encoded@.

In all cases, Play extracts this data and builds a @Map<String, String[]>@ which contains all the HTTP parameters. The key is the parameter name. The parameter name is derived from:

* The name of the dynamic part of the URI (as specified in the route)
* The name portion of a name-value pair taken from the Query String
* The contents of a x-www-urlform-encoded body.

h3. <a name="paramsmap">Using the params map</a>

The @params@ object is available to any Controller class (it is defined in the @play.mvc.Controller@ super class). This object contains all the HTTP parameters found for the current request.

For example:

bc. public static void show() {
    String id = params.get("id");
    String[] names = params.getAll("names");
}

You can also ask Play to do the type conversion for you:

bc. public static void show() {
    Long id = params.get("id", Long.class);
}

But wait, there are better ways to do this :)

h3. <a name="methodsignature">From the action method signature</a>

You can retrieve HTTP parameters directly from the action method signature. The Java parameter’s name must be the same as the HTTP parameter’s.

For example, in this request:

bc. /clients?id=1451

An action method can retrieve the @id@ parameter value by declaring an @id@ parameter in its signature:

bc. public static void show(String id) {
    System.out.println(id); 
}

You can use other Java types than String. In this case the framework will try to cast the parameter value to the correct Java type:

bc. public static void show(Long id) {
    System.out.println(id);  
}

If the parameter is multivalued, you can declare an Array argument:

bc. public static void show(Long[] id) {
    for(String anId : id) {
        System.out.println(anid); 
    }
}

or even a collection type:

bc. public static void show(List<Long> id) {
    for(String anId : id) {
        System.out.println(anid); 
    }
}

p(note). **Exceptions**
 
If the HTTP parameter corresponding to the action method argument is not found, the corresponding method argument is set to its default value (typically null for objects and 0 for primitive numeric types). If a value is found but can’t be properly cast to the required Java type, an error is added to the validation error collection and the default value is used.

h2. <a name="binding">Advanced HTTP to Java binding</a>

h3. <a name="simpletypes">Simple types</a>

All the native and common Java types are automatically bound:

@int@, @long@, @boolean@, @char@, @byte@, @float@, @double@, @Integer@, @Long@, @Boolean@, @Char@, @String@, @Byte@, @Float@, @Double@.

Note that if the parameter is missing in the HTTP Request, or if automatic conversion fails, Object types will be set to null and native types will be set to their default values.

h3. <a name="date">Date</a>

A date object can be automatically bound if the date’s string representation matches one of the following patterns:

* yyyy-MM-dd'T'hh:mm:ss'Z' // ISO8601 + timezone
* yyyy-MM-dd'T'hh:mm:ss" // ISO8601
* yyyy-MM-dd
* yyyyMMdd'T'hhmmss
* yyyyMMddhhmmss
* dd'/'MM'/'yyyy
* dd-MM-yyyy
* ddMMyyyy
* MMddyy
* MM-dd-yy
* MM'/'dd'/'yy

Using the <code>@As</code> annotation, you can specify the date format.

For example:

bc. archives?from=21/12/1980

bc. public static void articlesSince(@As("dd/MM/yyyy") Date from) {
    List<Article> articles = Article.findBy("date >= ?", from);
    render(articles);
}

You can of course refine the date format according to the language. For example:

bc.  public static void articlesSince(@As(lang={"fr,de","*"},
        value={"dd-MM-yyyy","MM-dd-yyyy"}) Date from) {
    List<Article> articles = Article.findBy("date >= ?", from);
    render(articles);
}

In this example, we specified that for the French and German languages the date format is @dd-MM-yyyy@ and for all the other languages it's @MM-dd-yyyy@. Please note that the lang value can be comma separated. The important thing is that the number of parameters for lang matches the number of parameters for value. 

If no <code>@As</code> annotation is specified, then Play! uses the default date format according to your locale. The "date.format configuration":configuration#date.format specifies the default date format to use.


h3. <a name="calendar">Calendar</a>

The calendar binding works exactly as with the date, except that Play is choosing the Calendar object according to your locale. The <code>@Bind</code> annotation can also be used.

h3. <a name="file">File</a>

File upload is easy with Play. Use a @multipart/form-data@ encoded request to post files to the server, and then use the @java.io.File@ type to retrieve the file object:

bc. public static void create(String comment, File attachment) {
    String s3Key = S3.post(attachment);
    Document doc = new Document(comment, s3Key);
    doc.save();
    show(doc.id);
}

The created file has the same name as the original file. It’s stored in a temporary directory and deleted at the end of the request. So you have to copy it in a safe directory or it will be lost.

The uploaded file's MIME type should normally be specified by the HTTP request’s @Content-type@ header. However, when uploading files from a web browser, this might not happen for uncommon types. In this case, you can map the file name’s extension to a MIME type, using the @play.libs.MimeTypes@ class.

bc. String mimeType = MimeTypes.getContentType(attachment.getName()); 

The @play.libs.MimeTypes@ class looks up the MIME type for the given file name’s extension in the file @$PLAY_HOME/framework/src/play/libs/mime-types.properties@ 

You can also add your own types using the "Custom MIME types configuration":configuration#mimetype.


h3. <a name="array">Arrays or collections of supported types</a>

All supported types can be retrieved as an Array or a collection of objects:

bc. public static void show(Long[] id) {
    …
}

or:

bc. public static void show(List<Long> id) {
    …
}

or:

bc. public static void show(Set<Long> id) {
    …
}

Play also handles the special case of binding a Map<String, String> like this:

bc. public static void show(Map<String, String> client) {
    …
}


A query string like the following:

bc. ?client.name=John&client.phone=111-1111&client.phone=222-2222

would bind the client variable to a map with two elements. The first element with key @name@ and value @John@, and the second with key @phone@ and value @111-1111, 222-2222@.

h3. <a name="pojo">POJO object binding</a>

Play also automatically binds any of your model classes using the same simple naming convention rules.

bc. public static void create(Client client ) {
    client.save();
    show(client);
}

A query string to create a client using this action would look like:

bc. ?client.name=Zenexity&client.email=contact@zenexity.fr

Play creates a Client instance and resolves HTTP parameter names to properties on the Client object. Unresolved parameters are safely ignored. Type mismatches are also safely ignored.

Parameter binding is done recursively, which means you can address complete object graphs:

bc. ?client.name=Zenexity
&client.address.street=64+rue+taitbout
&client.address.zip=75009
&client.address.country=France

In order to update a list of model objects, use array notation and reference the object’s ID. For example imagine the Client model has a list of Customer models declared as @List Customer customers@. To update the list of Customers you would provide a query string like the following:

bc. ?client.customers[0].id=123
&client.customers[1].id=456
&client.customers[2].id=789


h2. <a name="objectbinding">JPA object binding</a>

You can automatically bind a JPA object using the HTTP to Java binding.

You can provide the @user.id@ field yourself in the HTTP parameters. When Play finds the @id@ field, it loads the matching instance from the database before editing it. The other parameters provided by the HTTP request are then applied. So you can save it directly.

bc. public static void save(User user) {
    user.save(); // ok with 1.0.1
}

You can use JPA binding to modify complete object graphs in the same way as POJO mapping works, but you have to supply the ID for each sub object you intend to modify:

bc. user.id = 1
&user.name=morten
&user.address.id=34
&user.address.street=MyStreet 

h2. <a name="custombinding">Custom binding</a>

The binding system now supports more customization.

h3. <a name="as">@play.data.binding.As</a>

The first thing is the new <code>@play.data.binding.As</code> annotation that makes it possible to contextually configure a binding. You can use it for example to specify the date format that must be used by the @DateBinder@:

bc. public static void update(@As("dd/MM/yyyy") Date updatedAt) {
    …
}

The <code>@As</code> annotation also has internationalisation support, which means that you can provide a specific annotation for each locale:

bc. public static void update(
        @As(
            lang={"fr,de","en","*"},
            value={"dd/MM/yyyy","dd-MM-yyyy","MM-dd-yy"}
        )
        Date updatedAt
    ) {
    …
}

The <code>@As</code> annotation can work with all binders that support it, including your own binder. For example, using the @ListBinder@:

bc. public static void update(@As(",") List<String> items) {
    …
}

This binds a simple comma separated @String@ as a @List@.

h3. <a name="nobinding">@play.data.binding.NoBinding</a>

The new <code>@play.data.binding.NoBinding</code> annotation allows yous to mark non-bindable fields, resolving potential security issues. For example:

bc. public class User extends Model {
    @NoBinding("profile") public boolean isAdmin;
    @As("dd, MM yyyy") Date birthDate;
    public String name;
}
 
public static void editProfile(@As("profile") User user) {
    …
}

In this case, the @isAdmin@ field will never be bound from the @editProfile@ action, even if an malicious user includes a @user.isAdmin=true@ field in a fake form post.

h3. <a name="typebinder">play.data.binding.TypeBinder / TypeUnbinder</a>

The *@As* annotation also allows you to define a completely custom binder and/or unbinder. A custom binder / unbinder is subclass of @TypeBinder@ / @TypeUnbinder@ that you define in your project. For example:

bc. public class MyCustomStringBinder implements TypeBinder<String>, TypeUnbinder<String>  {
 
    public Object bind(String name, Annotation[] anns, String value, 
    Class clazz) {
        return "!!" + value + "!!";
    }
    
    @Override
    public void unBind(Map<String, Object> result, Object src, Class<?> srcClazz, 
        String name, Annotation[] annotations) throws Exception {
        String value = (String) src;
        if(value != null){
            value = value.replaceAll("^!!", "").replaceAll("!!$", "");
        }
        result.put(name, value);
    }
}

You can use it in any action, like:

bc. public static void anyAction(@As(binder=MyCustomStringBinder.class)
String name) {
    …
}

h3. <a name="global">@play.data.binding.Global</a>

Alternatively, you can define a global custom binder that will apply for the corresponding type. For example, you define a binder for the @java.awt.Point@ class like this:

bc. @Global
public class PointBinder implements TypeBinder<Point> {
 
    public Object bind(String name, Annotation[] anns, String value, 
    Class class) {
        String[] values = value.split(",");
        return new Point(
            Integer.parseInt(values[0]),
            Integer.parseInt(values[1])
        );
    }
}

As you see a global binder is a classical binder annotated with *@play.data.binding.Global*. An external module can contribute binders to a project, which makes it possible to define reusable binder extensions.


h2. <a name="result">Result types</a>

An action method has to generate an HTTP response. The easiest way to do this is to emit a Result object. When a Result object is emitted, the normal execution flow is interrupted and the method returns.

For example:

bc. public static void show(Long id) {
    Client client = Client.findById(id);
    render(client);
    System.out.println("This message will never be displayed !");
}

The @render(…)@ method emits a Result object and stops further method execution.

h3. <a name="text">Return some textual content</a>

The @renderText(…)@ method emits a simple Result event which writes some text directly to the underlying HTTP Response.

Example:

bc. public static void countUnreadMessages() {
    Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderText(unreadMessages);
}

You can format the text message using the Java standard formatting syntax:

bc. public static void countUnreadMessages() {
    Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderText("There are %s unread messages", unreadMessages);
}

h3. <a name="renderjson">Return a JSON String</a>

Play comes equiped with a method to simply return a JSON string, by making use of the @renderJSON(…)@ methods. These methods return a JSON string and set the response content type to @application/json@. 

You can specify your own JSON string, or you can pass in an @Object@, which will be serialised by the @GsonBuilder@.

Example:

bc. public static void countUnreadMessages() {
    Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderJSON("{\"messages\": " + unreadMessages +"}");
}

Alternatively, if you had a more complex object structure, you may wish to build the JSON using the @GsonBuilder@.

bc. public static void getUnreadMessages() {
    List<Message> unreadMessages = MessagesBox.unreadMessages();
    renderJSON(unreadMessages);
}

If you need more control over the JSON builder when passing an @Object@ to the @renderJSON(…)@ method, you can also pass in GSON serialisers and @Type@ objects to customise the output. 

h3. <a name="renderxml">Return an XML String</a>

As with the JSON methods, there are several methods for rendering XML directly from the controller. The @renderXml(…)@ methods return XML strings with the content type set to @text/xml@.

Here you can specify your own XML string, pass a @org.w3c.dom.Document@ object, or pass a POJO which will be serialised by the XStream serialiser.

Example:

bc. public static void countUnreadMessages() {
    Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderXml("<unreadmessages>"+unreadMessages+"</unreadmessages>");
}

Alternatively, you can use a @org.w3c.dom.Document@ object.

bc. public static void getUnreadMessages() {
    Document unreadMessages = MessagesBox.unreadMessagesXML();
    renderXml(unreadMessages);
}

h3. <a name="binary">Return binary content</a>

To serve binary data, such as a "file stored on the server":jpa#file, use the @renderBinary@ method. For example, if you have a @User@ model with a @play.db.jpa.Blob photo@ property, add a controller method to load the model object and render the image with the stored MIME type:

bc. public static void userPhoto(long id) {
   final User user = User.findById(id);
   response.setContentTypeIfNotSet(user.photo.type());
   InputStream binaryData = user.photo.get();
   renderBinary(binaryData);
} 

h3. <a name="attachment">Download a file as an attachment</a>

You can set an HTTP header to instruct the web browser to treat a binary response as an ‘attachment’, which generally results in the web browser downloading the file to the user’s computer. To do this, pass a file name as a parameter to the @renderBinary@ method, which causes Play to set the @Content-Disposition@ response header, providing a file name. For example, supposing the @User@ model from the previous example as a @photoFileName@ property:

bc. renderBinary(binaryData, user.photoFileName); 


h3. <a name="template">Execute a template</a>

If the generated content is complex, you should use a template to generate the response content.

bc. public class Clients extends Controller {
 
    public static void index() {
        render();    
    }
}

A template name is automatically deduced from the Play conventions. The default template path is resolved using the Controller and action names. 

In this example the invoked template is:

bc. app/views/Clients/index.html

h4. Add data to the template scope

Often the template needs data. You can add these data to the template scope using the @renderArgs@ object:

bc. public class Clients extends Controller {
 
    public static void show(Long id) {
        Client client = Client.findById(id);
        renderArgs.put("client", client);
        render();    
    }
}

During template execution, the @client@ variable will be defined.

For example:

bc. <h1>Client ${client.name}</h1>

h4. A simpler way to add data to the template scope

You can pass data directly to the template using @render(…)@ method arguments:

bc. public static void show(Long id) {
    Client client = Client.findById(id);
    render(client);    
}

In this case, the variables accessible by the template have the same name as the local Java variables.

You can pass more than one variable:

bc. public static void show(Long id) {
    Client client = Client.findById(id);
    render(id, client);    
}

p(note). **Important!**
 
You can only pass **local variables** in this way.


h4. Specify another template

If you don’t want to use the default template, you can specify your own template file using the @renderTemplate(…)@ method, by passing the template name as the first parameter:

Example:

bc. public static void show(Long id) {
    Client client = Client.findById(id);
    renderTemplate("Clients/showClient.html", id, client);    
}

h3. <a name="redirect">Redirect to another URL</a>

The @redirect(…)@ method emits a Redirect event that in turn generates an HTTP Redirect response.

bc. public static void index() {
    redirect("http://www.zenexity.fr");
}


h3. <a name="chaining">Action chaining</a>

There is no equivalent to the Servlet API @forward@. An HTTP request can only invoke one action. If you need to invoke another action, you have to redirect the browser to the URL able to invoke that action. In this way, the browser URL is always consistent with the executed action, and the **Back/Forward/Refresh** management is much easier.

You can send a Redirect response to any action, simply by invoking the action method in a Java way. The Java call is intercepted by the framework and the correct HTTP Redirect is generated.

For example:

bc. public class Clients extends Controller {
 
    public static void show(Long id) {
        Client client = Client.findById(id);
        render(client);
    }
 
    public static void create(String name) {
        Client client = new Client(name);
        client.save();
        show(client.id);
    }
}

With these routes:

bc. GET    /clients/{id}            Clients.show
POST   /clients                 Clients.create 

* The browser sends a POST to the @/clients@ URL.
* The Router invokes the @Clients@ controller’s @create@ action.
* The action method calls the @show@ action method directly.
* The Java call is intercepted and the Router reverse route generation creates the URL needed to invoke Clients.show with an id parameter.
* The HTTP Response is @302 Location:/clients/3132@.
* The browser then issues @GET /clients/3132@.
* …

h3. <a name="encoding">Customise web encoding</a>

Play emphasises the use of UTF-8, but there are situations where some responses, or the whole application, must use a different encoding.

h4. Custom encoding for current response

To change encoding for current response, you can do it like this in your controller:

bc. response.encoding = "ISO-8859-1";

When posting a form using an encoding other than the server default, you should include the encoding/charset twice in the form, both in the @accept-charset@ attribute and in a special hidden form field named @_charset_@. The @accept-charset@ attribute tells the browser which encoding to use when posting the from, and the form-field @_charset_@ tells Play what that encoding is:

bc. <form action="@{application.index}" method="POST" accept-charset="ISO-8859-1">
    <input type="hidden" name="_charset_" value="ISO-8859-1">
</form>

h4. Custom encoding for the entire application

Configure "application.web_encoding":configuration#application.web_encoding to specify which encoding Play uses when communicating with the browser.


h2. <a name="interceptions">Interceptions</a>

A controller can define interception methods. Interceptors are invoked for all actions of the controller class and its descendants. It’s a useful way to define treatments that are common to all actions: verifying that a user is authenticated, loading request-scope information…

These methods have to be @static@ or not but not @public@, but same as action methods, they can be either @static@ or non-static. You have to annotate these methods with a valid interception marker.

h3. <a name="before">@Before</a>

Methods annotated with the <code>@Before</code> annotation are executed before each action call for this Controller.

So, to create a security check:

bc. public class Admin extends Controller {
 
    @Before
    static void checkAuthentification() {
        if(session.get("user") == null) login();
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
    …
}

If you don’t want the @Before method to intercept all action calls, you can specify a list of actions to exclude:

bc. public class Admin extends Controller {
 
    @Before(unless="login")
    static void checkAuthentification() {
        if(session.get("user") == null) login();
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
 
    …
}

Or if you want the @Before method to intercept a list of action calls, you can specify a only param :

bc. public class Admin extends Controller {
 
    @Before(only={"login","logout"})
    static void doSomething() {
        …  
    }
    …
}

The @unless@ and @only@ parameters are available for the <code>@After</code>, <code>@Before</code> and <code>@Finally</code> annotations.

h3. <a name="after">@After</a>

Methods annotated with the <code>@After</code> annotation are executed after each action call for this Controller.

bc. public class Admin extends Controller {
 
    @After
    static void log() {
        Logger.info("Action executed ...");
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
 
    …
}

h3. <a name="catch">@Catch</a>

Methods annotated with <code>@Catch</code> are called if another action method throws the specified exception. The thrown exception is passed as a parameter to the @Catch method.

bc. public class Admin extends Controller {
	
    @Catch(IllegalStateException.class)
    public static void logIllegalState(Throwable throwable) {
        Logger.error("Illegal state %s…", throwable);
    }
    
    public static void index() {
        List<User> users = User.findAll();
        if (users.size() == 0) {
            throw new IllegalStateException("Invalid database - 0 users");
        }
        render(users);
    }
}

As with normal Java exception handling, you can catch a super-class to catch more exception types. If you have more than one catch method, you can specify their **priority** so that they are executed in order of priority (priority 1 is executed first).

bc. public class Admin extends Controller {
 
    @Catch(value = Throwable.class, priority = 1)
    public static void logThrowable(Throwable throwable) {
        // Custom error logging…
        Logger.error("EXCEPTION %s", throwable);
    }
 
    @Catch(value = IllegalStateException.class, priority = 2)
    public static void logIllegalState(Throwable throwable) {
        Logger.error("Illegal state %s…", throwable);
    }
 
    public static void index() {
        List<User> users = User.findAll();
        if(users.size() == 0) {
            throw new IllegalStateException("Invalid database - 0 users");
        }
        render(users);
    }
}


h3. <a name="finally">@Finally</a>

Methods annotated with the <code>@Finally</code> annotation are always executed after each action call to this Controller.
@Finally-methods are called both after successful action calls and if an error occurred.

bc. public class Admin extends Controller {
 
    @Finally
    static void log() {
        Logger.info("Response contains : " + response.out);
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
    …
}

If the method annotated with @Finally takes one argument of type Throwable, The Exception will be passed in if available:

bc. public class Admin extends Controller {
 
    @Finally
    static void log(Throwable e) {
        if( e == null ){
            Logger.info("action call was successful");
        } else{
            Logger.info("action call failed", e);
        }
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
    …
}


h3. <a name="hierarchy">Controller hierarchy</a>

If a Controller class is a subclass of another Controller class, interceptions are applied to the full Controller hierarchy.

h3. <a name="with">Adding more interceptors using the @With annotation</a>

Because Java does not allow multiple inheritance, it can be very limiting to rely on the Controller hierarchy to apply interceptors. But you can define some interceptors in a totally different class, and link them with any controller using the <code>@With</code> annotation.

Example:

bc. public class Secure extends Controller {
    
    @Before
    static void checkAuthenticated() {
        if(!session.containsKey("user")) {
            unAuthorized();
        }
    }
}    

And on another Controller:

bc. @With(Secure.class)
public class Admin extends Controller {
    
    …
}

h2. <a name="session">Session and Flash scopes</a>

If you have to keep data across multiple HTTP Requests, you can save them in the Session or the Flash scope. Data stored in the Session are available during the whole user session, and data stored in the flash scope are available to the next request only.

It’s important to understand that Session and Flash data are not stored in the server but are added to each subsequent HTTP Request, using the Cookie mechanism. So the data size is very limited (up to 4 KB) and you can only store String values.

Of course, cookies are signed with a secret key so the client can’t modify the cookie data (or it will be invalidated). The Play session is not aimed to be used as a cache. If you need to cache some data related to a specific session, you can use the Play built-in cache mechanism and use the *session.getId()* key to keep them related to a specific user session. 

Example:

bc. public static void index() {
    List messages = Cache.get(session.getId() + "-messages", List.class);
    if(messages == null) {
        // Cache miss
        messages = Message.findByUser(session.get("user"));
        Cache.set(session.getId() + "-messages", messages, "30mn");
    }
    render(messages);
}

The session expires when you close your web browser, unless you configure "application.session.maxAge":configuration#application.session.maxAge.

The cache has different semantics to the classic Servlet HTTP session object. You can’t assume that these objects will be always in the cache. So it forces you to handle the cache miss cases, and keeps your application fully stateless.

p(note). **Continuing the discussion**
 
The next important layer of the MVC model is the View layer, for which Play provides an efficient templating system with its %(next)"Template engine":templates%.
