Community contributed extensions

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.

if you prefer a more explicit style you can use renderHtml method to directly write to the response object

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, 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 {
  self: 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.

Scala Models have the following characteristics:

here is an example:

@Entity
class User(
  //fields

  @Email
  @Required
  var email: String,

  @Required
  var password: String,
  
  var fullname: String

) extends Model {
    //instance methods
    var isAdmin = false
    override def toString = email
}
object User extends QueryOn[User] {
//extra finder methods (if any) come here
}

Running queries against Models

The following methods are available as part of QueryOn:

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 find(q: String, ps: AnyRef*)(implicit m: M[T]) 
def find(q: String, params: Map[String, Any])(implicit m: M[T]): ScalaQuery[T]
def findOneBy(q: String, ps: AnyRef*)(implicit m: M[T]): T 
def all(implicit m: M[T]) 
def delete(q: String, ps: AnyRef*)(implicit m: M[T]) 
def deleteAll(implicit m: M[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 (assuming you defined the appropriate companion object):

User.count

or if you want to run a complex find query with bindings, that would look something like this:

QueryOn[Post].find("select distinct p.id from Post p join p.tags as t where t.name in (:tags) group by p.id having count(t.id) = :size", Map("tags" -> tags.toArray, "size" -> tags.size)).fetch

Another approach to access models is to utilize play.db.jpa.QueryOn object, so using the previous example: User.count becomes QueryOn[User].count

Usually, it’s recommended to use the companinon object form to provide query functionality (ie. User.count). The main advantage of the more generic QueryOn approach is that it’s working with both scala and java models.

model instance methods

The available instance methods are almost identical to the java version:

bc.def refresh(): this.type
def em()
def merge(): this.type
def save(): this.type
def delete(): this.type
def edit(name: String, params: java.util.Map[String,Array[String]]): this.type
def validateAndSave(): Boolean

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("[email protected]", "secret", "Bob").save()
  bob = User.find("byEmail", "[email protected]").first
  bob should not be (null)
  bob.fullname should be ("Bob")
 }
}

Scala console

play-scala comes with a console which can be really useful to try out various layers of your application.

here is an example session:

kola:yabe-with-scala phausel$ play scala:console
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.1-unstable-localbuild, http://www.playframework.org
~
15:43:17,805 INFO  ~ Starting /Users/phausel/workspace/play-scala/samples-and-tests/yabe-with-scala
15:43:17,809 INFO  ~ Module secure is available (/opt/local/lib/play-1.1-unstable-r777/modules/secure)
15:43:17,809 INFO  ~ Module scala is available (/Users/phausel/workspace/play-scala/samples-and-tests/yabe-with-scala/../..)
15:43:17,810 INFO  ~ Module crud is available (/opt/local/lib/play-1.1-unstable-r777/modules/crud)
15:43:19,300 WARN  ~ You're running Play! in DEV mode
~
~ Starting up, please be patient
~ Ctrl+D to stop
~
15:43:31,774 INFO  ~ Connected to jdbc:hsqldb:mem:playembed
15:43:33,130 INFO  ~ Application 'Yet Another Blog Engine' is now started !
Welcome to Scala version 2.8.0.Beta1-prerelease (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_17).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import models._
import models._

scala> User.count     
res0: Long = 3

commands are executed in a transaction, so changes to your models will be persistent

Modules wrapper

Play comes with 2 default modules (secure and crud) and the scala module provides wrapper for them. For example you can create a CRUD controller by mixing the CRUDFor trait:

object Companies extends Controller with CRUDFor[Company]

And you can make it secured by mixing the Secured trait as well:

object Companies extends Controller with CRUDFor[Company] with Secured

Yabe with Scala

A scala version of the blog application is bundled with play-scala and can be found here

Tutorial

a tutorial can be found here