You're reading from Mastering play framework for scala
All the supported routes are specified within a single file: routes
(by default). This makes it all the easier to figure out which one would be ideal.
The routes
file is compiled and if any errors occur, the compilation fails.
However, the routes
file is not a Scala object. So how does the compiler know what to do with the routes
file? To find this out, let's perform the following steps:
Let's create a project that displays a Hello, World! page. Now, define the
index.scala.html
home page as follows:<!DOCTYPE html> <html> <head> <title>Home</title> </head> <body> <h1>Hello, World!</h1> </body> </html>
We will use this in our controller in this way:
package controllers import play.api.mvc._ object AppController extends Controller { def index = Action { Ok(views.html.index()) } }
All we need to view our page is an entry in the
routes
file:# Home page GET ...
Play provides a feature to make HTTP calls using Scala methods. For every route defined, an equivalent Scala method is generated in the routes_ReverseRouting.scala
file. This is very convenient when making a request from within our Scala code, for example, within views such as the following:
@(tasks: List[Task], taskForm: Form[String]) @import helper._ @main("Task Tracker") { <h2>Task Tracker</h2> <div> @form(routes.TaskController.newTask) { @taskForm.globalError.map { error => <p class="error"> @error.message </p> } <form> <input type="text" name="taskName" placeholder="Add a new Task" required> <input type="submit" value="Add"> </form> } </div> <div> <ul> @tasks.map { task => <li> @form(routes.TaskController.deleteTask(task...
Any web application would require a style sheet or some other resources such as images, scripts, and so in. In a non-Play application, we would refer to these by figuring out the relative location of the file. For example, suppose that our application has a webapp
folder with index.html
, where we need to add a homePage.css
stylesheet, which is located at webapp/styles
. Now, the reference in index.html
would be something similar to the following:
<link rel="stylesheet" href="styles/homePage.css" />
Such relative paths can get very confusing and, at times, difficult to manage. In a Play application, the resources are placed in the public directory and can be accessed using a request. It is suggested that you split the public directory into three subdirectories for images, CSS style sheets, and JavaScript files for consistency, as shown in the following figure:
In addition to this, Play provides an asset controller by default to support requests, which can access resources (assets...
Play supports both static and dynamic request paths. If a request path cannot be matched to any of the defined routes, an Action not found
error is thrown at runtime, which is rendered using the devNotFound.scala.html
default template.
Dynamic paths are those that can be used for multiple requests and they may or may not result in a similar response. For example, the default assets path is a path used to serve resources:
GET /assets/*file controllers.Assets.at(path="/public", file)
The *
symbol indicates that anything following /assets/
until a space is found is the value of the file
variable.
Let's look at another way to make the path dynamic when we need to add one or more variables. For example, to get a user's details by userId
we use the following code:
GET /api/user/:userId controllers.UserController.getUser(userId)
By default, all the variables that occur in a path are of the String
type. If a conversion is required...
Many applications use additional parameters along with RESTful HTTP GET requests to obtain required information. Play supports configuring these request parameters as well.
Supposing we have a request to search users by their name, we could define this as follows:
GET /api/search/user controllers.UserController.search(name)
Therefore, we wouldn't need to get the parameters from the request in the action. We could let Play handle acquiring the parameters from the request and passing them to the action.
What do we do when the request parameters are optional? For example, what happens if we allow a search of users by their name where lastName
is optional.
We can specify Option
as the type for this request parameter. Therefore, the route definition would be similar to the following:
GET /api/search/user controllers.UserController.search(firstName:String, lastName:Option[String])
In addition to this, we can also specify the default value, if any...
The application works as expected but when the code is added to one or more base packages, the reverse routing doesn't work.
The routes are compiled, so when you make changes to the controllers, the project should be recompiled. In this case, run the clean
command and then compile the project. It is better to see whether the generated routing files reflect the changes made. If not, delete the target directory and compile the project.
In this chapter, we saw what an essential role routing plays in a Play application. As well as this, we saw the various default methods that Play provides to simplify the process of routing, in the form of assets, reverse routing, and so on.
In the next chapter, we will see how to define views in a Play application and also uncover how it works. As well as from the templating mechanism, the internals of building and using forms and internationalization will be covered in detail.