Scala

Play framework 2 quicktip: Scala console

When I first started to play with Scala, I was amazed by the Scala interactive interpreter (also known as REPL, read-evaluate-print-loop). It was one of those things that you never expected to find in a statically typed, compiled language like java or scala.

What would you say if we could have it for our play applications?… In scala OR JAVA! And yes, with tab completion and all the bells-and-whistles…

Well, thanks to Peter Hausel (@pk11) from the play dev team, I found out how to do it.

Just open a command prompt and type:

cd <path_to_your_play2_app>
play console

[info] Loading project definition from /home/sas/Dropbox/Public/devel/play/apps/play2/todo/project
[info] Set current project to todo (in build file:/home/sas/Dropbox/Public/devel/play/apps/play2/todo/)
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.6.0_31).
Type in expressions to have them evaluated.
Type :help for more information.

That’s it, you are at the scala console, and what’s best, with tab completion enabled!

Right there you can start playing with scala, and also with your application, like this:

scala> val contact = models.Contact(1, "new contact", "new address")
contact: models.Contact = Contact(1,new contact,new address)

You can test your views, and of course you can also issue imports to save yourself quite a few keystrokes

scala> import models._, views.html._
import models._
import views.html._

scala> val contacts = Seq( Contact(1, "@develsas", "Buenos Aires"), Contact(2, "@pk11", "Paris") )
contacts: Seq[models.Contact] = List(Contact(1,@develsas,Buenos Aires), Contact(2,@pk11,Paris))

scala> contact.list(contacts)
res1: play.api.templates.Html = 
<!DOCTYPE html>
<html>
    <head>
        <title>Contact list</title>
        <link rel="styles
[...]
<tr>
 <td>@develsas</td>
 <td>Buenos Aires</td>
</tr>
<tr>
 <td>@pk11</td>
 <td>Paris</td>
</tr>
[...]

But when you try to access your database you’ll get the following error:

scala> val contacts = Contact.all()
java.lang.RuntimeException: There is no started application
 at scala.sys.package$.error(package.scala:27)
[...]

That’s easy, you just have to start your application

scala> import play.core._
scala> new StaticApplication(new java.io.File("."))
[info] play - database [default] connected at jdbc:h2:data/db
[info] play - Application started (Prod)
res1: play.core.StaticApplication = play.core.StaticApplication@10cdd4

And now you can play arround interactively with your running application

scala> val contacts = Contact.all
contacts: Seq[models.Contact] = List(Contact(1,Paul,Boston), Contact(3,Paolo,Roma), Contact(4,Paulain,Paris), Contact(5,Abelardo,San Justo))

scala> val newContact = Contact(6, "new contact", "new address")
newContact: models.Contact = Contact(6,new contact,new address)

scala> Contact.insert(newContact)
res2: Int = 1

scala> val contacts = Contact.all
contacts: Seq[models.Contact] = List(Contact(1,Paul,Boston), Contact(3,Paolo,Roma), Contact(4,Paulain,Paris), Contact(5,Abelardo,San Justo), Contact(6,new contact,new address))

Now go check your database, you’ll see the new contact has been persisted to your db.

One last tip. If you are working against the in-memory database, and you have defined any evolution script, you’ll receive this message when you start the application form play console:

scala> new play.core.StaticApplication(new java.io.File("."))
[info] play - database [default] connected at jdbc:h2:mem:play
[warn] play - Your production database [default] needs evolutions! 

# --- Rev:1,Ups - 74ff2d1
[...]

[warn] play - Run with -DapplyEvolutions.default=true if you want to run them automatically (be careful)
PlayException: Database 'default' needs evolution! [An SQL script need to be run on your database.]
 at play.api.db.evolutions.EvolutionsPlugin$$anonfun$onStart$1.apply(Evolutions.scala:422)
[...]

The solution is quite easy, just start play with

play -DapplyEvolutions.default=true

And your evolution scripts will be automatically applied when you start the application.

Go ahead and give it a try. Grab, for example, the computer-database java demo

$ cd <path_to_your_play2_installation>/samples/java/computer-database
$ play -DapplyEvolutions.default=true

[computer-database] $ console
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.7.0_03).
Type in expressions to have them evaluated.
Type :help for more information.


scala> new play.core.StaticApplication(new java.io.File("."))
[info] play - database [default] connected at jdbc:h2:mem:play
[info] play - Application started (Prod)
res0: play.core.StaticApplication = play.core.StaticApplication@129796b

And now, just start playing around with your app

scala> val page = models.Computer.page(1, 10, "name", "asc", "")
page: com.avaje.ebean.Page[models.Computer] = com.avaje.ebeaninternal.server.query.LimitOffsetPage@d386c9

scala> val computerList = page.getList()
computerList: java.util.List[models.Computer] = BeanList size[10] hasMoreRows[true] list[models.Computer@137, models.Computer@20d, models.Computer@12e, models.Computer@1b7, models.Computer@12d, models.Computer@14a, models.Computer@14b, models.Computer@21f, models.Computer@98, models.Computer@1a2]

scala> computerList.get(0).name
res2: java.lang.String = ASCI White

Nevertheless, as soon as you start to play with the db, I faced a couple of problems. I could read from the database but I coudn’t write update nor inserts. I guess it’s the ebean voodoo magic that’s giving me troubles.

With the scala version, I could really go much further, look at this (go ahead, don’t be shy and copy-paste this code)

$ cd <path_to_your_play2_installation>/samples/scala/computer-database
$ play -DapplyEvolutions.default=true

[computer-database] $ console
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.7.0_03).
Type in expressions to have them evaluated.
Type :help for more information.

scala> new play.core.StaticApplication(new java.io.File("."))
[info] play - database [default] connected at jdbc:h2:mem:play
[info] play - Application started (Prod)
res0: play.core.StaticApplication = play.core.StaticApplication@1eaf4b3

scala> import models._, anorm._, play.api.db._, play.api.Play.current, anorm.SqlParser._

import models._
import anorm._
import play.api.db._
import play.api.Play.current
import anorm.SqlParser._

scala> // clean-up everything

scala> DB.withConnection { implicit connection => 
     SQL("delete from computer").executeUpdate()
     SQL("delete from company").executeUpdate()
     }
res3: Int = 42

scala> // just checking

scala> DB.withConnection { implicit connection => SQL("select count(*) from computer").as(scalar[Long].single) }
res7: Long = 0

scala> DB.withConnection { implicit connection => SQL("select count(*) from company").as(scalar[Long].single) }
res8: Long = 0

scala> Company.options
res9: Seq[(String, String)] = List()

Ok, let’s create a couple of companies

scala> 
DB.withConnection { implicit connection => 
  Seq((1, "my Company"), (2, "my second company")).map { company =>
    SQL("insert into company values ( %s, '%s')".format(company._1, company._2) ).executeUpdate()
  }
}
res50: Seq[Int] = List(1, 1)

scala> Company.options
res51: Seq[(String, String)] = List((1,my Company), (2,my second company))

And a couple of computers

scala> val newComputer = Computer(NotAssigned, "my computer", None, None, Some(1))
newComputer: models.Computer = Computer(NotAssigned,my computer,None,None,Some(1))

scala> Computer.insert(newComputer)
res67: Int = 1

scala> Computer.insert(Computer(NotAssigned, "my second comuter", None, None, Some(2)))

scala> 
DB.withConnection { implicit connection =>
  SQL("select * from computer").as(Computer.withCompany *)
}
res8: List[(models.Computer, Option[models.Company])] = List((Computer(1000,my computer,None,None,Some(1)),None), (Computer(1001,my second comuter,None,None,Some(2)),None))

We’ll, this example is a little exagerated, but I guess you get an idea of what you can do with the play console, so keep hacking!

Reference: Play framework 2 quicktip: interactively play with your application from the scala console from our JCG partner Sebastian Scarano at the Having fun with Play framework! blog.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Sebastian Nozzi
10 years ago

Anybody knows if it’s possible to interact with a *running* application from the console?

Lei Gao
Lei Gao
10 years ago

This is great! This helped me a lot. BTW: How to gracefully quit scala console or shutdown the static application?

Back to top button