Spray - Illegal response POIsFound … to GET request

9 views
Skip to first unread message

Jakub Stransky

unread,
May 1, 2015, 11:07:40 AM5/1/15
to spray...@googlegroups.com

what is the best practice or a common way how the spray routing gets connected to underlying akka aplication? I want through spray documentation and everywhere I just found pretty simple plain/text response with complete{"Hello"} or sort of those examples.

I am trying to implement simple REST WS which for GET and query parameters reply with application/json document. Underlying actor is receiving FindPOI msg and reply with FoundPOIs msg. I implemented jsonFormats from spray-json and imported SprayJsonSupport which should provide corresponding marshallers/un-marshallers.

I tried two approaches and unfortunately I wasn't able to make it work which is sign to me that I am missing probably some important concept here.

First attempt using RequestContext:

class GeoServiceApi(geoService: ActorRef)(implicit executionContext: ExecutionContext) extends Directives {
  implicit val timeout = Timeout(30.seconds)
  import spray.httpx.SprayJsonSupport._
  import POIsFoundProtocol._

  val route: Route = {
    pathPrefix("service") {
      pathPrefix("geo" / "poi") {
        get {
          parameters(('requestId.as[String], 'lat.as[Double], 'lng.as[Double])).as(TestClass) {
            tc => getPois(tc)}
        }
      }
    }
  }
  def getPois(par:TestClass)(ctx:RequestContext):Unit = {
    geoService.tell(FindPOI(par.item1,CentralLocation(par.item2,par.item3)),ctx.responder)
  }
}

case class TestClass(item1: String, item2: Double, item3: Double)

Getting Illegal response POIsFound ... to GET request error.

Second approach I tried handleWith and akka ask pattern:

class GeoServiceApi(geoService: ActorRef)(implicit executionContext: ExecutionContext) extends Directives {

  implicit val timeout = Timeout(30.seconds)

  import POIsFoundProtocol._
  import spray.httpx.SprayJsonSupport._

  val route: Route = {
    pathPrefix("service") {
      pathPrefix("geo" / "poi") {
        get {
          parameters(('requestId.as[String], 'lat.as[Double], 'lng.as[Double])) { (_,_,_) =>
            handleWith { i:Tuple3[String,Double,Double] => (geoService ? FindPOI(i._1, CentralLocation(i._2, i._3))).mapTo[POIsFound] }
          }
        }
      }
    }
  }

}

I am getting in this case "Request entity expected but not supplied".

For the first implementation attempt it seems that the responder expect to get exactly HttpResponse instead FoundPOIs message. Where this unmarshalling should happen? Does really my application actor reply with HttpResponse?

For second implementation - it seems that responder has timed out before the future for ask got completed and hence ended up in dead letter.

It seems to me that ask would be natural fit here due to the straight possibility of timing out but in contrary: Plenty of akka related blogs suggest to avoid ask where possible.

Could someone more experienced clarify and show the pattern how this integration is usually handled?

Thanks

Reply all
Reply to author
Forward
0 new messages