Play framework 2 quicktip: Scala console
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.
Anybody knows if it’s possible to interact with a *running* application from the console?
This is great! This helped me a lot. BTW: How to gracefully quit scala console or shutdown the static application?