2016-07-12 16 views
2

In meinem Akka-http Weg erhalte ich eine bestimmte Nachricht zurück, und ich will seinen Inhalt als Fehlermeldung wickeln wie:Akka: Wie wickeln Sie einen Nachrichteninhalt in eine HTTP-Antwort?

val response:Future[T] = (actor ? command).mapTo[T] 
    response match { 
     case err : Future[InvalidRequest] => 
      HttpResponse(408, entity = err.map(_.toJson).????) 
     case r : Future[T] => r.map(_.toJson) 
    } 

case class InvalidRequest(error:String) 

implicit val invalidRequestFormat = jsonFormat1(InvalidRequest) 

aber das funktioniert nicht. Wie kann ich es als Text im JSON-Format abbilden?

+0

Verwenden Sie Akkas Spray JSON Unterstützung für Ihren Marshalling zu JSON? – cmbaxter

+0

ja Ich habe die Frage aktualisiert – Randomize

+0

Ich denke, es könnte einfacher sein nur versuchen, den http-Status zu ändern 408 – Randomize

Antwort

2

Ich denke, ich kann eine generische Lösung für das bereitstellen, was Sie versuchen zu tun. Sie können durch die Schaffung einer Methode beginnen, die eine Route kehrt wie folgt:

def service[T:ClassTag](actor:ActorRef, command:Any) 
(implicit timeout:Timeout, _marshaller: ToResponseMarshaller[T]):Route = { 
    val fut = (actor ? command).mapTo[ServiceResponse] 
    onComplete(fut){ 
    case util.Success(ir:InvalidRequest) => 
     complete(StatusCodes.BadRequest, ir) 

    case util.Success(t:T) => 
     complete(t) 

    case util.Failure(ex) => 
     complete(StatusCodes.InternalServerError)   
    }  
} 

Diese Methode löst eine Anforderung an einen Schauspieler geliefert, über fragen und bekommt die Future das Ergebnis darstellt. Es verwendet dann die onComplete Direktive, um spezielle Behandlung auf den InvalidResponse Fall anzuwenden. Hier ist wichtig, dass Sie einen impliziten ToResponseMarshaller[T] im Geltungsbereich haben, da Sie dies für den Erfolgsfall benötigen.

Dann lassen Sie uns sagen, dass Sie die folgenden Klassen und Formatter definiert hatte:

trait ServiceResponse 
case class Foo(id:Int) extends ServiceResponse 
implicit val fooFormat = jsonFormat1(Foo) 
case class InvalidRequest(error:String) extends ServiceResponse 
implicit val invalidRequestFormat = jsonFormat1(InvalidRequest) 

Sie könnten Ihre neue service Methode in Ihrem Routingbaum wie folgt verwenden:

val routes:Route = { 
    path("api"/"foo"){ 
    get{ 
     service[Foo](fooActor, FooActor.DoFoo) 
    } 
    } 
} 

Das Problem mit Ihrem Beispiel ist, dass Sie nicht auf die Fertigstellung der Future gewartet haben, bevor Sie die Antwort erstellt haben. Sie haben versucht, auf den zugrunde liegenden Typ des Future zu passen, der durch Löschen zur Laufzeit eliminiert wird, also ist es keine gute Idee, auf diese Weise zu versuchen und zu vergleichen. Sie müssen stattdessen warten, bis es abgeschlossen ist und dann den Typ sehen, der hinter der Future steht.

+0

Vielen Dank. Ich benutze Akka 2.4.7 und die einzige gültige Signatur für 'complete' ist' def complete (m: ⇒ ToResponseMarshalable) 'also kann ich den Status nicht injizieren. – Randomize

+0

@Randomize, hast du die Chance, Akka 2.4.8 zu erreichen? – cmbaxter

+0

ja ich habe es getan. Es wurde jedoch nur Folgendes ausgeführt: 'complete (StatusCodes.BadRequest, ir.error)' – Randomize