Play 2.1 , Scala 2.10 and Slick 0.11.1
This post follow this famous tutorial !
Setup Slick in Play 2
If you don’t already have a Play 2 project, then create a new one after installing Play 2:
play new mySlickApp
Choose Scala as the language for the project.
The Slick library needs to be added to the Play project.
Edit the project/Build.scala file and update the dependencies:
1 2 3
Then if you are using an Eclipse or IntelliJ Play can automatically create the project for you using either:
Note that we created the project files after updating the dependencies, so the projects would be configured with the required libraries. If the dependencies change in the future, just re-run the commands to create the projects.
You can now start the application from within your project’s root directory:
Verify that the server is running by opening the following URL in your browser: http://localhost:9000
For local testing we will use an in-memory “h2” database. To setup Play to use that database, edit the conf/application.conf file and uncomment or add the following lines:
The final setup step is to provide Squeryl a database connection, but we still want to use the standard Play configuration system to get the database connection information. This is easily done by adding a Global class that can hook into the startup phase of the Play application lifecycle. Create a new file named app/Global.scala containing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
On application startup the configuration parameter will be used to determine which driver to use to setup the database connection.
If you reload the http://localhost:9000 webpage in your browser, everything should still be working and you should see the following message in the Play STDOUT log:
[info] play - database [default] connected at jdbc:h2:mem:play
Create an Entity
Now lets create a simple entity object that will be used to persist data into the database. Create a new file named app/models/Bar.scala containing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
This is a very simple entity that will store a list of Bar objects. Each Bar has a name and an id property for the primary key. The case class in Scala is immutable and basically supercharges a class, adding a number of syntactic conveniences. It also allows it to be used for pattern matching, which can be quite handy when matching form values returned from the client. The Bars object is an instance of Table Bar that Slick will map into the database.
Begineer about slick, I will not use evolution to create database but let slick create it for me, let’s modify Global.scala as bellow :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
reload the http://localhost:9000 webpage to create bar table on your local in-memory database. Test the Model
The testing support in Play 2 is very powerful and fits well with the Test Driven Development style. Play 2 with Scala uses specs2 as the default for testing but we prefer ScalaTest. Lets create a simple test for the Bar model object. Start by adding the ScalaTest dependency to the project and modifying the testOptions setting. Since scala 2.10.0-M6 scala-actor is an independent jar and must be add as dependencies. Update the project/Build.scala file to contain:
1 2 3 4 5 6 7 8 9 10
Now create a new file named test/BarSpec.scala containing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
This test uses a an in-memory database to run the test. The body of the test simply creates a new instance of Bar and tests that the id is equal to one. Different from Play 1, test are run from the command line using:
If the tests worked, then you should see the following message in the Play STDOUT log:
[mySlickApp] $ test
[info] A Bar
[info] - should be creatable
[info] Passed: : Total 1, Failed 0, Errors 0, Passed 1, Skipped 0
[success] Total time: 2 s, completed Oct 9, 2012 12:28:28 PM
If you’d like to have the tests run whenever the source changes then run:
You can keep both the ~run and ~test commands running in the background. This allows you to quickly test the application from both programmatic unit / functional tests and from manual browser tests. Creating Bars From a Web Form
Now lets add a basic web UI for creating new Bar objects. Note that this code will not compile until this entire section is completed.
First update the app/controllers/Application.scala file to contain:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
The barForm provides a mapping from a request parameter named name to the name property on the Bar case class (via it’s constructor). The index method has been updated to pass an instance of the barForm into the index template. We will update that template next. The addBar method binds the request parameters into an object named bar then in a session the bar is inserted into the database. Then the user is redirected back to the index page. If the request parameters could not be mapped to a Bar using the barForm then a BadRequest error is returned.
Now we need to update the app/views/index.scala.html template to contain:
1 2 3 4 5 6 7 8 9
The template now takes a Form[Bar] parameter which is passed from the index method on the Application controller. Then in the body of the template a new HTML form is rendered using Play 2’s form helper. The form contains an HTML field for the name and a submit button. Notice that the action of the form points from the route to the Application controller’s addBar method.
If you look in the console window at this point you will see the error “value addBar is not a member of controllers.ReverseApplication”. This is because the route file is compiled and the view is checked for a valid route. But we haven’t created a route yet, so edit the conf/routes file and add a new line with the following:
POST /bars controllers.Application.addBar
This creates a HTTP route that maps POST requests for the /bars URL to the addBar method.
Now refresh http://localhost:9000 in your browser and you should see the very basic form for adding new Bar objects. If successful, after adding a new Bar the browser should just redirect back to the index page.
Now lets add a RESTful service to the application that will return all of the Bar objects as JSON-serialized data. Start by adding a new method to the app/controllers/Application.scala file:
1 2 3 4 5 6 7
The getBars method fetches the Bar objects from the database using Slick dsl and then creates a JSON representation of the list of Bar objects and returns the JSON data.
Now add a new route to the conf/routes file:
GET /bars controllers.Application.getBars
This maps GET requests for /bars to the getBars method.
Try this out in your browser by loading: http://localhost:9000/bars
You should see a list of the Bar objects you’ve created serialized as JSON.
The syntax of the query demonstrates the power of Slick type-safe query language and the power of Scala to create DSLs. The json val is then returned in an Ok (HTTP 200 status code response) with the content type set to application/json (the value of JSON).