Enterprise Java

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.

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:
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:

name.scala.html

@(name: String)
<h1>Play Framework + Scala Example</h1>
<h2>Hello @name</h2>
    • Create our HelloPathParamsController with name() under “controllers” folder as shown below:

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

Play! Framework Path, Query Route Default Params - Test Play Scala Path Parameters with Web Browser
Test Play Scala Path Parameters with Web Browser

    • Access http://localhost:9000/hello/ram url from POSTMAN REST client as shown below and observe the result

Play! Framework Path, Query Route Default Params - Test Play Scala Path Parameters with REST Client
Test Play Scala Path Parameters with REST Client

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:

age.scala.html

@(age: Int)
<h1>Play Framework + Scala Example</h1>
<h2>Hello, you are @age years old.</h2>
    • Develop another function age() our HelloPathParamsController with under “controllers” folder as shown below:

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() and age() from HelloPathParamsController
    • 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

Play! Framework Path, Query Route Default Params -age with Web Browser
Test Play Scala Path Params – age with Web Browser

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.

Play! Framework Path, Query Route Default Params - age with Browser
Test Play Scala Path Params – age with Browser

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 our HelloPathParamsController as shown below:

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:

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

Play! Framework Path, Query Route Default Params - Test Play Scala Multiple Path Parameters With Browser
Test Play Scala Multiple Path Parameters With Browser

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:

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:

HelloQueryParamsController.scala

package controllers

import javax.inject.Inject
import play.api.mvc.InjectedController

class HelloQueryParamsController @Inject() extends InjectedController {

}
    • Add hello function to our HelloQueryParamsController as shown below:

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:

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

Play! Framework Path, Query Route Default Params - Test Play Scala Query Params With Browser
Test Play Scala Query Params With Browser

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

Test Play Scala Missing Query Parameters with Browser

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:

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:

HelloRouteDefaultsController.scala

package controllers

import javax.inject.Inject
import play.api.mvc.InjectedController

class HelloRouteDefaultsController @Inject() extends InjectedController {
}
    • Add hello function to our HelloRouteDefaultsController as shown below:

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:

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

Play! Framework Path, Query Route Default Params - Test Play Scala Route Default Params with Browser
Test Play Scala Route Default Params with Browser

    • When we access http://localhost:9000/hello?name=ram&age=35 url from web browser, we will observe the following results

Play! Framework Path, Query Route Default Params
Test Play Scala Route Default Params with given values With Browser

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:

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:

HelloRouteFixedValuesController.scala

package controllers

import javax.inject.Inject
import play.api.mvc.InjectedController

class HelloRouteFixedValuesController @Inject() extends InjectedController {
}
    • Add hello function to our HelloRouteDefaultsController as shown below:

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:

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

Play! Framework Path, Query Route Default Params
Test Play Scala – Route Fixed Values with Browser

    • When we access http://localhost:9000/hello?name=scala&age=51 url from web browser, we will observe the following results

Play! Framework Path, Query Route Default Params
Test Play Scala – Route Fixed Values with given data

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:

10. Download the Source Code

That were a Play! Framework + Scala: Path Params, Query Params, Routing Default and Fixed values Web Application Examples Tutorial.

Download
You can download the full source code of this example here: Play! Framework Path, Query and Route Default Params Example

Rambabu Posa

Ram did his Masters in IS(Information Systems) from Andhra University, India. He has 10+ years of experience in Java Ecosystem and 6+ years of experience in Scala/Python Ecosystem, BigData and GCP world. He is author of “Scala Reactive Programming” book. Apart from Java, Python and Scala, he is good at Spark, PySpark, Apache BEAM, REST API, NoSQL, BigData Hadoop Stack, Cloud, Groovy, Play Framework, Akka Toolkit, Lagom Framework, Kafka, Kubernetes (K8S), TDD, BDD,Agile and much more. He likes sharing his knowledge through writing tutorials and books.
Subscribe
Notify of
guest

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

0 Comments
Inline Feedbacks
View all comments
Back to top button