h1. Writing Play controllers in Scala

Play controllers are the most important part of any Play applications. A Play Scala application share the same concepts than a classical Play application but use a more functional way to describe actions.

h2. Scala controllers are Objects

A Controller is a Scala singleton object, hosted by the @controllers@ package, and subclassing @play.mvc.Controller@. In Scala you can declare as many controllers you want in the same file.

This a classical controller definition:

bc. package controllers {
    
    import play._
    import play.mvc._
    
    object Users extends Controller {
        
        def show(id:Long) = Template("user" -> User.findById(id))
        
        def edit(id:Long, email:String) = {
            User.changeEmail(id, email)
            Action(show(id))
        }
        
    }
    
}

Because Scala provides the native notion of **Singleton objects** we don't need anymore to deal with Java static methods while keeping to ability to reference statically any action like @show(id)@.

h2. Action methods return values

A Play controller usually uses imperative orders like @render(…)@ or @forbidden()@ to trigger the response generation. On the contrary an action methods written in Scala is seen as functions and must return a value. This value will be used by the framework to generate the HTTP response resulting of the request.

An action method can of course return several kind of values depending of the request (like for example a @Template@ or an @Forbidden@ value). 

Here are listed the typical return types:

<hr>

h3. Ok

Returning the @Ok@ value will generate an empty **200 OK** response.

bc. def index = Ok

<hr>

h3. Html

Returning an @Html@ value will generated a **200 OK** response filled with the HTML content. The response content type will be automatically set to **text/html**.

bc. def index = Html("<h1>Hello world!</h1>")

You can also generate Html by calling a template.

<hr>

h3. Xml

Returning an @Xml@ value will generated a **200 OK** response filled with the XML content. The response content type will be automatically set to **text/xml**.

bc. def index = Xml(<message>Hello world!</message>)

<hr>

h3. Text

Returning an @Text@ value will generated a **200 OK** response filled with the text content. The response content type will be automatically set to **text/plain**.

bc. def index = Text("Hello world!")

<hr>

h3. Json

Returning an @Json@ value will generated a **200 OK** response filled with the text content. The response content type will be automatically set to **application/json**.

bc. def index = Json("{message: 'Hello world'}")

You can also try to pass any Scala object and Play will try to serialize it to JSON:

bc. def index = Json(users)

p(note). However currently the JSON serialization mechanism comes from Java and can not work as exepected with complex Scala structures. 
 
A workaround is to use a Scala dedicated JSON serialization library, for example "Lift JSON":https://github.com/jonifreeman/liftweb/tree/master/lift-json/, and use it as @Json(JsonAST.render(users))@

<hr>

h3. Created

Returning the @Created@ value will generate an empty **201 Created** response.

bc. def index = Created

<hr>

h3. Accepted

Returning the @Accepted@ value will generate an empty **202 Accepted** response.

bc. def index = Accepted

<hr>

h3. NoContent

Returning the @NoContent@ value will generate an empty **204 No Content** response.

bc. def index = NoContent

<hr>

h3. Action

If an action method return a @Action@ value, Play will redirect the Browser to the corresponding action, using the action method arguments to properly resolve the proper URL.

bc. def index = Action(show(3))

Note that here @show(3)@ is a **by-name** parameter, and the corresponding methid will not been invoked. Play will resolve this call as an URL (typically something like **users/3**), and will issue an HTTP redirect to this URL. The action will then be invoked in a new request context.

p(note). In a Java controller you achieve the same result by calling directly the corresponding action method. Using Scala **call by name** concept allow to keep the compiler checked and typesafe redirection without any language hack.

<hr>

h3. Redirect

Returning the @Redirect@ value will generate an empty **301 Moved Permanently** response.

bc. def index = Redirect("http://www.google.com")

You can optionnaly specify a second argument to switch between **301** and **302** response status code.

bc. def index = Redirect("http://www.google.com", false)

<hr>

h3. NotModified

Returning the @NotModified@ value will generate an empty **304 Not Modified** response.

bc. def index = NotModified

You can also specify an **ETag** to the response:

bc. def index = NotModified("123456")

<hr>

h3. BadRequest

Returning the @BadRequest@ value will generate an empty **400 Bad Request** response.

bc. def index = BadRequest

<hr>

h3. Unauthorized

Returning the @Unauthorized@ value will generate an empty **401 Unauthorized** response.

bc. def index = Unauthorized

You can optionnaly specify a realm name:

bc. def index = Unauthorized("Administration area")

<hr>

h3. Forbidden

Returning the @Forbidden@ value will generate an empty **403 Forbidden** response.

bc. def index = Forbidden

You can optionnaly specify an error message:

bc. def index = Forbidden("Unsufficient permissions")

<hr>

h3. NotFound

Returning the @NotFound@ value will generate an empty **404 Not Found** response.

bc. def index = NotFound

You can optionnaly specify a resource name:

bc. def index = NotFound("Article not found")

Or use a more classical HTTP method, resource Path combination:

bc. def index = NotFound("GET", "/toto")

<hr>

h3. Error

Returning the @Error@ value will generate an empty **500 Internal Server Error** response.

bc. def index = Error

You can optionnaly specify an error message:

bc. def index = Error("Oops…")

Or specify a more specific error code:

bc. def index = Error(503, "Not ready yet…")

h2. Return type inference

You can also directly use the inferred return type to send the action result. For example using a String:

bc. def index = "<h1>Hello world</h1>"

Or you can even use the built-in XML support to write XHTML in a literal way:

bc. def index = <h1>Hello world</h1>

If the return type looks like a binary stream, play will automatically render the response as binary. So generating a captcha image using the built-in Captcha helper can be written as:

bc. def index = Images.captcha

h2. Controller interceptors

Controller interceptors work almost the same way than for Java controller. You simply have to annotate any controller method with the corresponding interceptor annotation:

bc. @Before def logRequests {
    println("New request…")
}

You see that here, the @logRequests@ method does not return any value. So the request execution will continue by invoking the next interceptors and eventually the action method.

But you can also write some interceptor that return a value:

bc. @Before def protectActions = {
    Forbidden
}

Here the execution will stop, and the @Forbidden@ value will be used to generate the HTTP response.

If you want to continue the request execution, just make your interceptor return @Continue@:

bc. @Before def protectActions = {
    session("isAdmin") match {
        case Some("yes") => Continue
        case _ => Forbidden("Restricted to administrators")
    }
}


h2. Mixing controllers using Traits

Scala Traits can be used to compose controller more effeciently by mixing several aspects. You can define both action methods and interceptors in a controller Trait.

For example the following **Secure** trait add a seucrity interceptor to any controller applying the Trait:

bc. trait Secure {
    self:Controller =>
    
    @Before checkSecurity = {
        session("username") match {
            case Some(username) => renderArgs += "user" -> User(username)
                                   Continue
            case None => Action(Authentication.login)
        }
    }
    
    def connectedUser = renderArgs("user").get
    
}

p(note). Note that here we use the @self:Controller =>@ notation to indicate that this Trait can only be mixed with a @Controller@ type.

And you can use it to create a secured controller:

bc. object Application extends Controller with Secure {
    
    def index = <h1>Hello {connectedUser.name}!</h1>
    
}

<hr>

There is also small differences about %(next)"Data binding":dataBinding%