Documentation

Scala support

The 1.1 release of play will include support for the Scala programming language. Thanks to the flexibility of the play framework architecture, the Scala support is provided with a simple module. You just need to enable the scala module in the conf/application.conf file.

module.scala=${play.path}/modules/scala

Then you can write all or parts of your play application using scala. You can of course mix it with Java.

We are in very very active development on this stuff. You can try it for now as an experimental feature. Don’t expect to write a complete play application in Scala right now.

For a quick overview of the scala support, you can watch this Scala screencast

Create a new application, with Scala support

You can automatically create a scala ready application, by using the --with option of the play new command. Just try:

play new myApp --with scala

The play application will be created as usual, but if you look at the controllers package, the Application.java file is now replaced by a Application.scala file:

package controllers
 
import play._
import play.mvc._
 
object Application extends Controller {
    
    def index = render()
    
}

It is very close to the Java version of the default Application controller.

Now just run the application as usual using play run and it will display the standard welcome page. Now just edit the Application.scala file to replace the render() call:

def index = "Hello scala !"

Refresh the page, and see the magic.

As always, if you make a mistake, play will just show you the error in a perfect way; (it’s just more difficult now to forget the trailing semicolon)

Direct return types

As shown above, for simple action methods you can directly use the inferred return type to send the action result. For example using a String:

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

And 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 use renderBinary(). So generating a captcha image using the built-in Captcha helper can be written as:

def index = Images.captcha

Action parameters, and scala default arguments

You can declare some action parameter the same way you do it in Java:

def index(name: String) = <h1>Hello {name}</h1>

To big plus of scala is the ability to define some default values to these parameters:

def index(name: String = "Guest") = <h1>Hello {name}</h1>

This way if the name HTTP parameter is missing, play will use the default argument value.

Controllers composition using traits

A controller can use several traits to combine several interceptor.

Let’s define a Secure trait:

package controllers
 
import play.__
import play.mvc.__ 
 
trait Secure extends Controller {
	
	@Before
	def check {
		session("user") match {
			name: String => info("Logged as %s", name)
			_ => Security.login
		}
	}
	
}

And you can them use it in the Application controller:

package controllers
 
object Application extends Controller with Secure {
	
	def index = "Hello world"
	
}

How to define and access Models

Models can be defined not only in java but in scala as well. Unfortunately, due to the differences between the two langauges the Model API somewhat differs from the java version.

Main differences

here is an example:

@Entity
class User(
  //fields
  @Email
  @Required
  var email: String,
  @Required
  var password: String,
  var fullname: String
) extends Model[User] {
    //instance methods
    var isAdmin = false
    override def toString = email
}
//finder methods
object User extends Model[User] {
    def connect(email: String, password: String) = {
        User.find("byEmailAndPassword", email, password).first
    }
}

Running queries against Scala Models from Scala classes

The following methods are available when running queries against scala models:

def count(implicit m: M[T]) = i.count(m)
def count(q: String, ps: AnyRef*)(implicit m: M[T])  
def findAll(implicit m: M[T]) 
def findById(id: Any)(implicit m: M[T]) 
def findBy(q: String, ps: AnyRef*)(implicit m: M[T]) 
def find(q: String, ps: AnyRef*)(implicit m: M[T]) 
def all(implicit m: M[T]) 
def delete(q: String, ps: AnyRef*)(implicit m: M[T]) 
def deleteAll(implicit m: M[T]) = 
def findOneBy(q: String, ps: AnyRef*)(implicit m: M[T]): T 
def create(name: String, ps: play.mvc.Scope.Params)(implicit m: M[T]): T

As you can see, it’s really similar to the java API, so for example to count the number of users, you can just call count on the User class:

User.count

One known limitation of the Scala Model API is that the save method is not working in a chained call fashion, so you always need to execute it on an instance, as you can see it later at the unit testing section

Running queries against Java Models from Scala classes

In certain situations it might be desirable to query models written in java from scala.
Since java models are not extending from the scala Model trait, Play needs to provide an alternative query interface which comes in the form of QueryRunner trait and the corresponding companion object. In order to utilize this feature you either need to import the query methods like

import play.db.jpa.QueryRunner._

or you can mix in the trait

class MyController extends Controller with QueryRunner {...} 

and the API is defined like this:

def count[T](implicit m: M[T]) = i.count(m)
def count[T](q: String, ps: AnyRef*)(implicit m: M[T])  
def findAll[T](implicit m: M[T]) 
def findById[T](id: Any)(implicit m: M[T]) 
def findBy[T](q: String, ps: AnyRef*)(implicit m: M[T]) 
def find[T](q: String, ps: AnyRef*)(implicit m: M[T]) 
def all[T](implicit m: M[T]) 
def delete[T](q: String, ps: AnyRef*)(implicit m: M[T]) 
def deleteAll[T](implicit m: M[T]) = 
def findOneBy[T <: JPASupport](q: String, ps: AnyRef*)(implicit m: M[T]): T 
def create[T <: JPASupport](name: String, ps: play.mvc.Scope.Params)(implicit m: M[T]): T

Using the previous example User.count becomes count[User]

Unit Testing

ScalaTest support is integrated into Play, so one can easily write unit tests using ScalaTest, for example:

class SpecStyle extends UnitTest with FlatSpec with ShouldMatchers {
"Creating a user" should "be succesfull" in {
  val user = new User("bob@gmail.com", "secret", "Bob")
  user.save
  bob = User.find("byEmail", "bob@gmail.com").first
  bob should not be (null)
  bob.fullname should be ("Bob")
 }
}

Tutorial

We are currently writing a version of the play tutorial for scala.

Read The play tutorial (Scala version).