I'm working on a REST service using Akka HTTP (in Scala). I would like a parameter that is passed in to a http get request to be converted to the ZonedDateTime type. The code works fine if I try to use String or Int but fails with a ZonedDateTime type. The code would look like so:
parameters('testparam.as[ZonedDateTime])
Here is the error that I'm seeing:
Error:(23, 35) type mismatch;
found : akka.http.scaladsl.common.NameReceptacle[java.time.ZonedDateTime]
required: akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet
parameters('testparam.as[ZonedDateTime]){
If I add more than one parameter to the list I get a different error:
Error:(23, 21) too many arguments for method parameters: (pdm: akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet)pdm.Out
parameters('testparam.as[ZonedDateTime], 'testp2){
I found this in the documentation when I was researching the problem http://doc.akka.io/japi/akka-stream-and-http-experimental/2.0/akka/http/scaladsl/server/directives/ParameterDirectives.html and I tried the workaround of adding import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet
along with using Scala 2.11 but the problem persisted.
Could someone please explain what I'm doing wrong and why the ZonedDateTime type doesn't work? Thanks in advance!
Here is a code snippet that should reproduce the problem I'm seeing
import java.time.ZonedDateTime
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import scala.io.StdIn
object WebServer {
def main(args: Array[String]) {
implicit val system = ActorSystem("my-system")
implicit val materializer = ActorMaterializer()
// needed for the future flatMap/onComplete in the end
implicit val executionContext = system.dispatcher
val route =
path("hello") {
get {
parameters('testparam.as[ZonedDateTime]){
(testparam) =>
complete(testparam.toString)
}
}
}
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
}
}
As ZonedDateTime
is not natively unmarshalled by Akka-HTTP, you will need to provide a custom unmarshaller to the parameters
directive.
This functionality is briefly described in the docs here.
Your unmarshaller can be created from a function by using Unmarshaller.strict
, e.g.
val stringToZonedDateTime = Unmarshaller.strict[String, ZonedDateTime](ZonedDateTime.parse)
This example assumes your param is provided in an ISO format. If it's not, you'll need to amend the unmarshalling function.
You can then use the unmarshaller passing it to the parameters directive:
parameters('testparam.as(stringToZonedDateTime)){ testparam =>
complete(testparam.toString)
}
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