Play! Framework Path, Query and Route Default Params Example
In my previous post, we have discussed about Play Framework basics with HelloWorld example. I hope you have experimented that example and waiting for next step in this series. If not done, better to go through my previous post first at Play! Framework Hello World Example. It will give you some basic idea about “How Play Framework and Scala SBT Project works”.
In this post, we are going to discuss about few more Play Framework basics like Path Parameters, Query Parameters, Routing Default Parameters and Routing Fixed Values Parameters in detail with some suitable examples. We will also discuss what is the best approach between Path and Query Parameters to develop REST APIs. We will try to develop separate SBT project for each concept so that we can play or evaluate them very well. Lets start now.
Table Of Contents
1. Technologies used
In this post, we are going to use the following technologies to develop our Play-Scala SBT based projects:
- Scala 2.12.6
- Play Framework 2.6.13
- SBT 1.1.5
- IntelliJ IDEA
Before exploring the next steps, please try to install Java 1.8 or later version and the above mentioned software. Let us start developing our Play Scala Web Application in the next section.
2. Path Parameters
Path Parameters or Path Variables are used to transfer data and to identify a REST Resource uniquely. Sometimes, they are also known as “URI Parameters”. In this post, I use both Parameters and Params words interchangeably.
Path Params Syntax:
:pathparam
To define Path Params, we use “:” (colon) first then some variable name like “pathparam”. For instance, please observe the following REST API or EndPoint to understand this concept:
GET /hello/:name
Here :name
is a Path parameter. When users want to make a call to this EndPoint, they have to pass a value to that variable as shown below:
GET /hello/ram
Here :name
is assigned to “ram” value. Similarly, we can use multiple Path Parameters if required as shown below:
GET /hello/:name/:message
Let us start developing one example to understand “How Play Framework supports Path Parameters” concept very well in the coming section.
2.1 Path Parameters Example
In this section, we will develop Play Framework Scala Web Application to explore how to use Path parameters to send dynamic data.
We are going to use IntelliJ IDE and SBT build tool to develop this application. If you are using IntelliJ IDE Ultimate Edition, first please create a Play Framework web application using IDE. If you are using IntelliJ IDE CE (Community Edition), please download the Play Scala Starter project from the following Lightbend’s Play Framework Examples GitHub location:
https://github.com/playframework/play-scala-starter-example
I have renamed this project as “PlayFrameworkScalaPathParamsExample”, imported into IntelliJ IDE and deleted all files.
Then please continue the following steps to develop our HelloWorld application:
- First four steps are same like my previous post. Please refer it at Play! Framework Hello World Example
- Add a new routing to “routes” file under “conf” folder as shown below
routes
## Hello Path Params Controller GET /hello/:name controllers.HelloPathParamsController.name(name: String)
Description
- Our Endpoint is identified using this URI:
/hello/:name
- It contains
{name}
as a Path Parameter - When user makes a call to this Endpoint with some value in place of
{name}
Path Parameter as shown below:
- Our Endpoint is identified using this URI:
GET /hello/ram
This “ram” value is passed to HelloPathParamsController.name(name: String)
function.
- Define Scala View Template
name.scala.html
under “views” folder with the following content:
- Define Scala View Template
name.scala.html
@(name: String) <h1>Play Framework + Scala Example</h1> <h2>Hello @name</h2>
- Create our
HelloPathParamsController
withname()
under “controllers” folder as shown below:
- Create our
HelloPathParamsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloPathParamsController @Inject() extends InjectedController { def name(name: String) = Action { Ok(views.html.name(name)) } }
We have developed our initial application components successfully. It’s time test it in the next section.
Note: If you want to understand Play/Scala/SBT based project structure, please refer my previous post at Play! Framework Hello World Example.
2.2 Test Path Params
In this section, we will up and run our Play Scala Based application and test it.
- To up and running our application using sbt command
$cd PlayFrameworkScalaPathParamsExample $sbt run
- Access
http://localhost:9000/hello/ram
url from web browser as shown below and observe the result
- Access
- Access
http://localhost:9000/hello/ram
url from POSTMAN REST client as shown below and observe the result
- Access
Wow great! We have successfully developed and tested on Play + Scala application to test Path Parameters. We will learn few more things about Path Params now.
- Develop Scala View Template
age.scala.html
under “views” folder with the following content:
- Develop Scala View Template
age.scala.html
@(age: Int) <h1>Play Framework + Scala Example</h1> <h2>Hello, you are @age years old.</h2>
- Develop another function
age()
ourHelloPathParamsController
with under “controllers” folder as shown below:
- Develop another function
HelloPathParamsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloPathParamsController @Inject() extends InjectedController { // Other Code def age(age: Int) = Action { Ok(views.html.age(age)) } }
- Add new Route as in “routes” file as shown below:
routes
## Hello Path Params Controller GET /hello/:name controllers.HelloPathParamsController.name(name: String) GET /hello/:age controllers.HelloPathParamsController.age(age: Int)
Description
Here we can observe that the following things from the above two Endpoints:
- Both Endpoints have “GET” as HTTP request method
- Both Endpoints have different Path Parameters: {name} for first one and {age} for second one
- Both Endpoints are referring two different functions
name()
andage()
fromHelloPathParamsController
- Make sure our application is up and running
- When we access
http://localhost:9000/hello/35
url from web browser, we will observe the following results
Yes we will see the same results as /hello/{name}
Endpoint. As per age.scala.html
, we should the following output:
Play Framework + Scala Example Hello, you are 35 years old.
Why and what is the problem with those two Endpoints? Why both URLs are getting same text? Let us explore those things now.
- First and foremost thing we need to remember is, in Play Framework each Path Parameter is of type
String
- Even though we are trying to differentiate
/hello/35
URI’s Path Parameter “35” as Int, Play Framework converts it into a String only - That’s why whether we call
/hello/ram
or/hello/35
, they both are calling the same “GET /hello/{name}” Endpoint - They both are making a call to
HelloPathParamsController.name()
function
How to solve this problem? How to design those Endpoints to work as per our expectations? In REST API Development, Design of API or Endpoints URIs uniquely is very important. They play very vital role in RESTful Web Services or REST API development because they should refer the Resources uniquely. Let us redesign these two Endpoints in different way as shown below in the “routes” file:
routes
## Hello Path Params Controller GET /hello/:name controllers.HelloPathParamsController.name(name: String) #GET /hello/:age controllers.HelloPathParamsController.age(age: Int) GET /hello/age/:age controllers.HelloPathParamsController.age(age: Int)
We have given URI like /hello/age/:age
to differentiate it with /hello/:name
to identify both REST API Resources uniquely.
There is no change in Controller. As shown above, We can use “#” to comment unused text in “routes” file.
Lets up and running the server if not, then access the new Endpoint to see the results.
We can use zero or one or more Path Parameters in designing and developing our REST API. So far we have discussed about how to use single Path Parameter. In this section, let us develop and explore about how to use multiple Path Parameters.
We have developed two examples: one for name and another for age details. Now we want to combine both into one Endpoint.
- Add new EndPoint to the “routes” file as shown below:
routes
## Hello Path Params Controller GET /hello/:name controllers.HelloPathParamsController.name(name: String) #GET /hello/:age controllers.HelloPathParamsController.age(age: Int) GET /hello/age/:age controllers.HelloPathParamsController.age(age: Int) GET /hello/:name/:age controllers.HelloPathParamsController.nameAge(name:String, age: Int)
Here we have used two Path Parameters in our new Endpoint /hello/:name/:age
: one is to say hello to user using name and another to display user age details.
We have mapped URI’s two Path Parameters to Action as two parameters: nameAge(name:String, age: Int)
. First Path Parameter is mapped to name
function argument and second parameter is mapped to age
function argument.
- Add new function
nameAge
to ourHelloPathParamsController
as shown below:
- Add new function
HelloPathParamsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloPathParamsController @Inject() extends InjectedController { def name(name: String) = Action { Ok(views.html.name(name)) } def age(age: Int) = Action { Ok(views.html.age(age)) } def nameAge(name:String, age: Int) = Action { Ok(views.html.nameAge(name, age)) } }
This is our final HelloPathParamsController
controller implementation.
- Develop Scala View Template
nameAge.scala.html
under “views” folder with the following content:
- Develop Scala View Template
nameAge.scala.html
@(name: String, age: Int) <h1>Play Framework + Scala Example</h1> <h2>Hello @name, you are @age years old.</h2>
Here, nameAge.scala.html
template is taking two parameters: name and age.
- Make sure our application is up and running
- When we access
http://localhost:9000/hello/ram/35
url from web browser, we will observe the following results
Thats it about Play Framework’s Path Parameters concepts. Now move on to next concept: Query Parameters.
3. Query Parameters
Like Path Parameters, Play Framework has support for Query Parameters. Both Path and Query Parameters are used to send dynamic data from Client to Server.
Query Parameters are useful for doing some additional activities on REST Resources like Filtering, Sorting, Searching, Grouping etc. We can define Query Parameters as “key=value” pairs in a URL. They are separated by ampersand (&).
GET /hello?key=value
We separate URI and Query Parameters by using Question Mark (?). Here URI is “/hello” and Query Parameter is “key=value”. Let us observe the following example:
GET /hello?name=ram
We can design our REST Endpoints using either zero or one or more Query Parameters. Multiple Parameters are separated by ampersand (&) as shown below:
GET /hello?key1=value1&key2=value2
We will develop couple of examples to explore these concepts one by one in the coming sections.
3.1 Query Parameters Example
In this section, we will develop Play/Scala/SBT project to explore how Query Parameters works in sending dynamic data between Client and Server.
We are going to use IntelliJ IDE and SBT build tool to develop this application. If you are using IntelliJ IDE Ultimate Edition, first please create a Play Framework web application using IDE. If you are using IntelliJ IDE CE (Community Edition), please download the Play Scala Starter project from the following Lightbend’s Play Framework Examples GitHub location:
https://github.com/playframework/play-scala-starter-example
I have renamed this project as “PlayFrameworkScalaQueryParamsExample”, imported into IntelliJ IDE and deleted all files.
Then please continue the following steps to develop our HelloWorld application:
- First four steps are same like my previous post. Please refer it at Play! Framework Hello World Example
- Add new EndPoint to the “routes” file as shown below:
routes
## Hello Query Params Controller GET /hello controllers.HelloQueryParamsController.hello(name: String, age: Int)
If we observe above Endpoint, it’s URI has just “/hello”. We just removed everything from URI, No Path Parameters to pass data. Then how do we send that data from Client to Server? How this Controller receives that data and process this request?
As we discussed about Query Parameters syntax in the previous section, we can send our required data as shown below:
/hello?name=Ram&age=35
Here we are passing both required values by using Query Parameters so that our Controller process this request.
- Create
HelloQueryParamsController
controller as shown below under “controllers” package:
- Create
HelloQueryParamsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloQueryParamsController @Inject() extends InjectedController { }
- Add
hello
function to ourHelloQueryParamsController
as shown below:
- Add
HelloQueryParamsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloQueryParamsController @Inject() extends InjectedController { def hello(name: String, age:Int) = Action { Ok(views.html.hello(name, age)) } }
- Develop Scala View Template
hello.scala.html
under “views” folder with the following content:
- Develop Scala View Template
hello.scala.html
@(name: String, age: Int) <h1>Play Framework + Scala Example</h1> <h2>Hello @name, you are @age years old.</h2>
Here, hello.scala.html
template is taking two parameters: name and age.
- Make sure our application is up and running
- When we access
http://localhost:9000/hello?name=ram&age=35
url from web browser, we will observe the following results
Like this we can use any number of Query Parameters to pass dynamic data from Client to Server.
3.2 Query Parameters Error Scenarios
In this section, we will explore couple of important Error Scenarios which are related to Query Parameters. Sometimes, Less or Un-experienced Users may do these mistakes.
If Users forget or miss in sending those Query Parameters or send only few Parameters, they will get the following error message:
case-1: Missing both name and age parameters
URL like http://localhost:9000/hello
case-2: Missing only name parameter
URL like http://localhost:9000/hello?age=35
, then we will see the following error message
Bad Request For request 'GET /hello?age=35' [Missing parameter: name]
case-3: Missing only age parameter
URL like http://localhost:9000/hello?name=ram
, then we will see the following error message
Bad Request For request 'GET /hello?name=ram' [Missing parameter: age]
4. Path Vs Query Parameters
In the last two sections, we have discussed about two important concepts which are supported by Play Framework: Path Parameters and Query Parameters. We have developed couple of examples. In this section, we will compare both concepts and decide which one is good or best to develop REST API (RESTful Web services).
We can observe the following differences between Path and Query Parameters:
- Path Parameters are mainly useful for identifying REST Resources uniquely. Query Parameters are useful to do some additional activities like Filtering, Grouping, Sorting etc.
- Path Parameters syntax is very simple where as Query Parameter’s syntax is bit awkward and error prone.
Path Parameters Syntax:
GET /hello/:name/:age
Query Parameters Syntax:
GET /hello?name=ram&age=35
- Both Path and Query Parameters should NOT be secured or confidential values because they are exposed to user and every one.
Note: To design best REST API, it is recommended to follow these two rules:
- Path Parameters are used to identify a specific resource or resources uniquely
- Query Parameters are used to Filter, Sort, Group etc resources
4.1 Path and Query Parameters Best Practices
When we design our REST API using Path and Query Parameters, it is highly recommended to follow these Best Practices:
- If possible, its better to use single word names for both Parameters
- Both Parameaters names should be in lower case
- If we use more than one word names, better to separate them using hyphen (-) like “month-year”
GET /emp/:month-year
- Use meaningful names
5. Route Default Parameters
Play Framework supports “Default Parameters” for Routes. Sometimes Params are optional. User can send them to send dynamic data from Client to Server or can use default values.
When we define default values to Route Parameters, our application uses them only when user does not send that data. However, Users are welcome to override those default values.
Route Default Parameters Syntax:
parameName: paramType ?= defaultValue
Here we should use “?=” (question mark followed by assignment) symbol to assign default value to a Route parameter.
Please refer the following example to understand this syntax very well.
name: String ?= "User"
We can use zero, one or more default values in a Play Framework routing.
If you are still not clear, don’t worry. We will develop one simple example to understand it in the coming section.
5.1 Route Default Parameters Example
In this section, we will develop one Play/Scala/SBT example to understand “How Play Framework supports Default Parameters?” concept very well.
We are going to use IntelliJ IDE and SBT build tool to develop this application. If you are using IntelliJ IDE Ultimate Edition, first please create a Play Framework web application using IDE. If you are using IntelliJ IDE CE (Community Edition), please download the Play Scala Starter project from the following Lightbend’s Play Framework Examples GitHub location:
https://github.com/playframework/play-scala-starter-example
I have renamed this project as “PlayFrameworkScalaRouteDefaultParamsExample”, imported into IntelliJ IDE and deleted all files.
Then please continue the following steps to develop our HelloWorld application:
- First four steps are same like my previous post. Please refer it at Play! Framework Hello World Example
- Add new EndPoint to the “routes” file as shown below:
routes
## Hello Route Default values Controller GET /hello controllers.HelloRouteDefaultsController.hello(name: String ?= "User", age: Int ?= 35)
- Create
HelloRouteDefaultsController
controller as shown below under “controllers” package:
- Create
HelloRouteDefaultsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloRouteDefaultsController @Inject() extends InjectedController { }
- Add
hello
function to ourHelloRouteDefaultsController
as shown below:
- Add
HelloRouteDefaultsController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloRouteDefaultsController @Inject() extends InjectedController { def hello(name: String, age: Int) = Action { Ok(views.html.hello(name, age)) } }
- Develop Scala View Template
hello.scala.html
under “views” folder with the following content:
- Develop Scala View Template
hello.scala.html
@(name: String, age: Int) <h1>Play Framework + Scala Example</h1> <h2>Hello @name, you are @age years old.</h2>
Here, hello.scala.html
template is taking two parameters: name and age.
- Make sure our application is up and running
- When we access
http://localhost:9000/hello
url from web browser, we will observe the following results
- When we access
http://localhost:9000/hello?name=ram&age=35
url from web browser, we will observe the following results
- When we access
That means if we have Default values in a Route, we can use them as it is or override them if required.
Thats it about Play Framework supported Route Default Parameters.
6. Route Fixed Values
Like Route Default Params discussed in the previous section, Play Framework supports “Fixed Values” to Route Parameters. Sometimes, we should not allow users to send data from Client to Server or we need to assign some fixed values to Route Parameters.
Route Fixed Values Syntax:
paramName: paramType = fixedValue
Unlike Route Default values, here we should use “=” (assignment) operator to set fixed values to Rout params. Please observe the following example to understand this syntax very well:
name: String = "ram"
We can use zero, one or more fixed values in a Play Framework routing.
If you are still not clear, don’t worry. We will develop one useful example to understand it in the coming section.
6.1 Route Fixed Values Example
Let us start developing one example to understand this concept very well.
We are going to use IntelliJ IDE and SBT build tool to develop this application. If you are using IntelliJ IDE Ultimate Edition, first please create a Play Framework web application using IDE. If you are using IntelliJ IDE CE (Community Edition), please download the Play Scala Starter project from the following Lightbend’s Play Framework Examples GitHub location:
https://github.com/playframework/play-scala-starter-example
I have renamed this project as “ PlayFrameworkScalaRouteFixedValuesExample”, imported into IntelliJ IDE and deleted all files.
Then please continue the following steps to develop our HelloWorld application:
- First four steps are same like my previous post. Please refer it at Play! Framework Hello World Example
- Add new EndPoint to the “routes” file as shown below:
routes
## Hello Route Fixed values Controller GET /hello controllers.HelloRouteFixedValuesController.hello(name: String = "ram", age: Int = 35)
- Create
HelloRouteDefaultsController
controller as shown below under “controllers” package:
- Create
HelloRouteFixedValuesController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloRouteFixedValuesController @Inject() extends InjectedController { }
- Add
hello
function to ourHelloRouteDefaultsController
as shown below:
- Add
HelloRouteFixedValuesController.scala
package controllers import javax.inject.Inject import play.api.mvc.InjectedController class HelloRouteFixedValuesController @Inject() extends InjectedController { def hello(name: String, age: Int) = Action { Ok(views.html.hello(name, age)) } }
- Develop Scala View Template
hello.scala.html
under “views” folder with the following content:
- Develop Scala View Template
hello.scala.html
@(name: String, age: Int) <h1>Play Framework + Scala Example</h1> <h2>Hello @name, you are @age years old.</h2>
Here, hello.scala.html
template is taking two parameters: name and age.
- Make sure our application is up and running
- When we access
http://localhost:9000/hello
url from web browser, we will observe the following results
- When we access
http://localhost:9000/hello?name=scala&age=51
url from web browser, we will observe the following results
- When we access
That means if we have fixed values in a Route, we should use them as it is. Its not possible to override them.
Thats it all about Play Framework Route Fixed Values Parameters.
7. Play Framework Route: Default Vs Fixed values
In the last two sections, we have explored two important features of Play Framework Routes: Default and Fixed values. Let us compare those two concepts here:
- Syntax: Both Route Default and Fixed values have difference syntax.
Route Default values syntax:
name: String ?= "ram"
Route Fixed values syntax:
name: String = "ram"
- Override: We can overide Route Default values if required where as not possible this for Route Fixed values because they are fixed and not changeable.
- Usage: We use Route default values frequently in most of the projects where Fixed values are rarely used concept.
8. Conclusion
In this post, we have discussed mainly 4 important concepts which are useful for Play/Scala Developers: Path and Query Params, Route Default and Fixed values.
Path params are very important and useful concept, most frequently used concept in designing REST API in most of the projects. They have very simple syntax. We can do something using Query Prams too, but they have some awkward syntax and not recommended to use it for all scenarios.
We can use Path Params to identify a REST Resource where as Query Params are useful to sort, filter, group etc. of REST Resources.
Play Framework supports both Default and Fixed values for Routes to ease the development process. Route Default value is most frequently used concept, where as Route Fixed values is rarely used concept.
We will discuss some more useful Play Framework concepts in my coming posts. Please stay tuned.
9. Reference
If you are interested to learn more details about Play Framework, Scala Language and SBT tool, please refer the following important websites:
- Play Framework website: https://www.playframework.com
- Play Framework Scala API: https://www.playframework.com/documentation/2.6.x/api/scala/index.html#package
- Scala Language: https://www.scala-lang.org
- Scala API: https://www.scala-lang.org/api/2.12.6
- Scala SBT tool: https://www.scala-sbt.org
10. Download the Source Code
That were a Play! Framework + Scala: Path Params, Query Params, Routing Default and Fixed values Web Application Examples Tutorial.
You can download the full source code of this example here: Play! Framework Path, Query and Route Default Params Example