Community contributed extensions

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.

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:

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

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:


Ok

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

def index = Ok


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.

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

You can also generate Html by calling a template.


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.

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


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.

def index = Text("Hello world!")


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.

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

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

def index = Json(users)

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, and use it as Json(JsonAST.render(users))


Created

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

def index = Created


Accepted

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

def index = Accepted


NoContent

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

def index = NoContent


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.

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.

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.


Redirect

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

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

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

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


NotModified

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

def index = NotModified

You can also specify an ETag to the response:

def index = NotModified("123456")


BadRequest

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

def index = BadRequest


Unauthorized

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

def index = Unauthorized

You can optionnaly specify a realm name:

def index = Unauthorized("Administration area")


Forbidden

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

def index = Forbidden

You can optionnaly specify an error message:

def index = Forbidden("Unsufficient permissions")


NotFound

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

def index = NotFound

You can optionnaly specify a resource name:

def index = NotFound("Article not found")

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

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


Error

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

def index = Error

You can optionnaly specify an error message:

def index = Error("Oops…")

Or specify a more specific error code:

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

Return type inference

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

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

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

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:

def index = Images.captcha

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:

@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:

@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:

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

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:

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
    
}

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:

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


There is also small differences about Data binding