This post is over 6 months old. Some details, especially technical, may have changed.

Working with Play apps in the Console

Having spent a fair amount of time working with Clojure in the last 6 months I've become rather accustomed to the REPL driven development approach. If you're unfamiliar with this approach I recommend reading/viewing Jay Fields post on the topic. Long story short RDD involves writing a small bits of code and executing them immediately. This gives you immediate feedback without having to write tests or start an entire system each time. You can of course make your REPL based experimentation more concrete by saving your work off as a set of tests once your code has settled down a bit.

Like Clojure, and unlike Java, Scala supports the concept of REPL driven development and I've been using it more often since my exposure to its charms in Clojure. Of course Scala syntax is a lot meatier (and I do mean a lot) than Clojure syntax so there is a bit more friction but every now and again its faster when you just want to poke around a concept or idea.

A common example when working with Play is querying the application database with Anorm. The one problem here is that to use Anorm and the Play provided extensions you need to have a running Play instance that it can extract configuration values from.

For example if we tried to get all the users from a database we could write something like this via the console (sbt console or activator console in the root of our project)

scala> import play.api.db._
scala> import anorm._
scala> DB.withConnection { implicit connection => SQL"SELECT * FROM users".map(mapUser).list() }

But this would result in an error.

java.lang.RuntimeException: There is no started application
  at scala.sys.package$.error(package.scala:27)
  at play.api.Play$$anonfun$current$1.apply(Play.scala:71)
  at play.api.Play$$anonfun$current$1.apply(Play.scala:71)
  at scala.Option.getOrElse(Option.scala:120)
  at play.api.Play$.current(Play.scala:71)
  ... 43 elided

Bummer. Thankfully Play provides a quick way to stand up an running instance which can be used in the console

scala> new play.core.StaticApplication(new java.io.File("."))
[info] play - database [default] connected at jdbc:h2:file:./data/db
[info] play - Application started (Prod)
res18: play.core.StaticApplication = play.core.StaticApplication@22a730f2

Now if we try our query again

scala> DB.withConnection { implicit connection => SQL"SELECT * FROM users".map(mapUser).list() }
res19: Seq[scala.collection.immutable.Map[String,String]] = List(Map(username -> kouphax, password -> JHGW$FSWF$KJJK$3231))

To be super clean we can even stop the running instance

scala> play.api.Play.stop()

StaticApplication isn't perfect. For instance it will start your application in production mode but for my needs this has been acceptable. If you do want to provide greater control over how your application is started then look no further than the StaticApplication source.

class StaticApplication(applicationPath: File) extends ApplicationProvider {

  val application = new DefaultApplication(applicationPath, this.getClass.getClassLoader, None, Mode.Prod)

  Play.start(application)

  def get = Success(application)
  def path = applicationPath
}

Using this knowledge you could create your own application instance using DefaultApplication and ask Play to start it using Play.start(application).

Published in Scala on July 11, 2014