I am new to Play Framework. I am able to send simple data types like string, integer etc directly via the request and access them in the Back end Java method.
When I try doing this in the route file,
GET /food/fetchMealInfo/:noOfDays/:dateSelected controllers.trackandplan.FoodController.fetchMealInfo(noOfDays : Integer, dateSelected : Date)
I am getting an error saying
Compilation error
not found: type Date
What is the correct, safe and clean way to transfer a date object from a front end AngularJS application to the Java application in Play Framework. Please guide.
You have a couple options. The slightly easier way to understand is to simply transmit the date/time as a Long
(unix timestamp), and convert it to a Date
in the controller method.
GET /food/fetchMealInfo/:noOfDays/:dateSelected controllers.trackandplan.FoodController.fetchMealInfo(noOfDays: Integer, dateSelected: Long)
public static Result fetchMealInfo(Integer noOfDays, Long dateSelected) {
Date date = new Date(dateSelected.longValue());
...
}
The more sophisticated way would be to use a PathBindable
, which would allow you to use Date
within the routes file itself. However, you would still need to transmit the Date
as a Long
(the PathBindable
would make the conversion if possible). Unfortunately, since we obviously don't have control over Date
, we have to implement PathBindable
in Scala, and not Java (Java would require implementing an interface for Date
, which we can't).
app/libs/PathBinders.scala
package com.example.libs
import java.util.Date
import play.api.mvc.PathBindable
import scala.util.Either
object PathBinders {
implicit def bindableDate(implicit longBinder: PathBindable[Long]) = new PathBindable[Date] {
override def bind(key: String, value: String): Either[String, Date] = {
longBinder.bind(key, value).right.map(new Date(_))
}
override def unbind(key: String, date: Date): String = key + "=" + date.getTime().toString
}
}
In order for the routes file to be able to pick this up, you'll need to add the following to your build.sbt
file:
PlayKeys.routesImport += "com.example.libs.PathBinders._"
PlayKeys.routesImport += "java.util.Date"
Now you can use Date
within your routes file (as Long
), without the need to handle it specially for every method that uses it.
GET /food/fetchMealInfo/:noOfDays/:dateSelected controllers.trackandplan.FoodController.fetchMealInfo(noOfDays: Integer, dateSelected: Date)
Note: This might not compile straight away if you're using an older Play version. I tested it with Play 2.3.8 and sbt 0.13.5.
It is also possible to modify the PathBindable
I made here to use an underlying String
instead, and accept a specific date format.
package com.example.libs
import java.util.Date
import java.text.SimpleDateFormat
import play.api.mvc.PathBindable
import scala.util.{Either, Failure, Success, Try}
object PathBinders {
implicit def bindableDate(implicit stringBinder: PathBindable[String]) = new PathBindable[Date] {
val sdf = new SimpleDateFormat("yyyy-MM-dd")
override def bind(key: String, value: String): Either[String, Date] = {
for {
dateString <- stringBinder.bind(key, value).right
date <- Try(sdf.parse(dateString)).toOption.toRight("Invalid date format.").right
} yield date
}
override def unbind(key: String, date: Date): String = key + "=" + sdf.format(date)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With