2016-05-24 2 views
1

Ich verließ die Akka-Welt für ein paar Monate und anscheinend habe ich mein Mojo verloren. Ich versuche, einen Webservice zu schreiben, der basierend auf dem Accept-Header entweder ein XML- oder ein JSON-Dokument zurückgibt.Wie fordere ich JSON oder XML mit Akka-http?

Allerdings kann ich die Marshaller nicht zum Arbeiten bringen (gibt 406 zurück, akzeptiert nur text/plain). Das ist, was ich habe:

trait MyMarshallers extends DefaultJsonProtocol with SprayJsonSupport with ScalaXmlSupport { 
    implicit def ec: ExecutionContext 

    implicit val itemJsonFormat = jsonFormat3(MyPerson) 


    def marshalCatalogItem(obj: MyPerson): NodeSeq = 
    <MyPerson> 
     <id> 
     {obj.ID} 
     </id> 
     <name> 
     {obj.Name} 
     </name> 
     <age> 
     {obj.Age} 
     </age> 
    </MyPerson> 

    def marshalCatalogItems(items: Iterable[MyPerson]): NodeSeq = 
    <Team> 
     {items.map(marshalCatalogItem)} 
    </Team> 

    implicit def catalogXmlFormat = Marshaller.opaque[Iterable[MyPerson], NodeSeq](marshalCatalogItems) 

    implicit def catalogItemXmlFormat = Marshaller.opaque[MyPerson, NodeSeq](marshalCatalogItem) 

    implicit val catalogMarshaller: ToResponseMarshaller[Iterable[MyPerson]] = Marshaller.oneOf(
    Marshaller.withFixedContentType(MediaTypes.`application/json`) { catalog ⇒ 
     HttpResponse(entity = HttpEntity(ContentType(MediaTypes.`application/json`), 
     catalog.map(i ⇒ MyPerson(i.ID, i.Name, i.Age)) 
      .toJson.compactPrint)) 
    } 
    , 
    Marshaller.withOpenCharset(MediaTypes.`application/xml`) { (catalog, charset) ⇒ 
     HttpResponse(entity = HttpEntity.CloseDelimited(ContentType(MediaTypes.`application/xml`, HttpCharsets.`UTF-8`), 
     Source.fromFuture(Marshal(catalog.map(i => MyPerson(i.ID, i.Name, i.Age))) 
      .to[NodeSeq]) 
      .map(ns ⇒ ByteString(ns.toString())) 
    ) 
    ) 
    } 
) 
} 

und meine Route sieht wie folgt aus:

class MyService extends MyMarshallers { 
    implicit val system = ActorSystem("myService") 
    implicit val materializer = ActorMaterializer() 
    implicit val ec: ExecutionContext = system.dispatcher 

    ... 
    def route = ... 
     (get & path("teams")) { 
       parameters('name.as[String]) { id => 
       complete { 
        getTeam(id) 
       } 

       } 
     ... 

} 

Und wenn ich / anfordern, ich Klartext, aber wenn ich bitten application/xml oder application/json, ich bekomme eine 406.

Wie entscheidet AKKA-HTTP, welche Inhaltstypen akzeptiert werden? Ich habe gerade alles auf Akka 2.4.6 aktualisiert.

Antwort

0

Entschuldigung, ich habe es herausgefunden. Der obige Code hatte zwei Probleme, von denen das Problem behoben:

  • Ausgabe 1 - geändert fromIterator statt fromFuture im XML Einweiser zu verwenden.
  • Problem 2 - meine Methode getTeam() gab ein Iterable zurück. Ich habe das in eine Seq geändert.

Jetzt funktioniert alles.

+0

Hey Will! Ich habe bemerkt, dass du viele Fragen über Akka stellst, aber nur selten Antworten akzeptierst. Bitte tun Sie dies, wenn die Antwort Ihren Bedürfnissen entspricht. Es ermutigt Benutzer, mehr zu helfen. Vielen Dank! – expert

+1

Ich bin mir nicht sicher, wo ich keine Antworten akzeptiere. Wenn ich es nicht getan habe, muss es eine Auslassung sein. Allerdings brauche ich manchmal ein paar Stunden, um nach Antworten zu suchen. Und zum Beispiel kann ich meine eigene Antwort für weitere 10 Stunden nicht akzeptieren. –

+1

Nun, ich überprüfte meine letzten paar Fragen, und ich akzeptierte alle Antworten. Bis auf zwei, die ich nicht hatte zurückkommen und nach Antworten suchen können. Danke, dass du mich für nichts schlecht gemacht hast. :( –