2017-07-28 1 views
1

Je travaille sur un service REST utilisant Akka HTTP (en Scala). J'aimerais qu'un paramètre transmis à une requête http get soit converti en le type ZonedDateTime. Le code fonctionne correctement si j'essaie d'utiliser String ou Int mais échoue avec un type ZonedDateTime. Le code ressemblerait à ceci:Scala Akka Paramètre de diffusion HTTP en tant que java.time.ZonedDateTime

parameters('testparam.as[ZonedDateTime]) 

Voici l'erreur que je vois:

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]){ 

Si j'ajoute plus d'un paramètre à la liste que je reçois une autre erreur:

Error:(23, 21) too many arguments for method parameters: (pdm: akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet)pdm.Out 
      parameters('testparam.as[ZonedDateTime], 'testp2){ 

J'ai trouvé cela dans la documentation lorsque je recherchais le problème http://doc.akka.io/japi/akka-stream-and-http-experimental/2.0/akka/http/scaladsl/server/directives/ParameterDirectives.html et j'ai essayé la solution de contournement de l'ajout de import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet avec Scala 2.11 mais le problème persista.

Quelqu'un pourrait-il expliquer ce que je fais de mal et pourquoi le type ZonedDateTime ne fonctionne pas? Merci d'avance!

Voici un extrait de code qui devrait reproduire le problème que je vois

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

Répondre

4

Comme ZonedDateTime est pas nativement unmarshalled par HTTP Akka, vous devez fournir une coutume unmarshaller à la directive parameters.

Cette fonctionnalité est brièvement décrite dans les documents here.

Votre unmarshaller peut être créé à partir d'une fonction en utilisant Unmarshaller.strict, par ex.

val stringToZonedDateTime = Unmarshaller.strict[String, ZonedDateTime](ZonedDateTime.parse) 

Cet exemple suppose que votre param est fourni dans un format ISO. Si ce n'est pas le cas, vous devrez modifier la fonction unmarshalling.

Vous pouvez ensuite utiliser le unmarshaller passage à la directive paramètres:

parameters("testparam".as(stringToZonedDateTime)){ 
      (testparam) => 
       complete(testparam.toString) 
      }