1
votes

I'm trying to my first Spray + Akka project work.

Although this looks like straight forward, I still get a type error with the unmarshaller (which I don't need, I'm returning a String because I'll produce nothing but XML in the end.

package com.example.actors

import akka.actor.{Props, ActorContext, Actor}
import akka.util.Timeout
import spray.http.CacheDirectives.`max-age`
import spray.http.HttpHeaders.`Cache-Control`
import spray.routing._
import spray.http._
import MediaTypes._
import scala.concurrent.duration._

class SprayActor extends Actor with DefaultService {
  def actorRefFactory = context
  def receive = runRoute(defaultRoute)
}

trait DefaultService extends HttpService {
  def actorRefFactory: ActorContext

  lazy val feedActor = actorRefFactory.system.actorOf(Props[MainFeedActor])

  import akka.pattern.ask

  implicit val timeout = Timeout(5 seconds) // needed for `?` below

  val defaultRoute = path("rss") {
    get {
      respondWithMediaType(`text/xml`) {
        respondWithHeaders(`Cache-Control`(`max-age`(0))) {
          complete {
            (feedActor ? "rss").mapTo[String]
          }
        }
      }
    }
  }
}

class MainFeedActor extends Actor {
  val log = Logging(context.system, this)

  override def receive: Receive = {
    case "rss" => "<xml>test</xml>"
  }

Here is the compiler error:

[error] src/main/scala/com/example/actors/SprayActor.scala:31: type mismatch;
[error]  found   : scala.concurrent.Future[String]
[error]  required: spray.httpx.marshalling.ToResponseMarshallable
[error]             (feedActor ? "rss").mapTo[String]
[error]                                      ^
[error] one error found
[error] (compile:compile) Compilation failed
1

1 Answers

3
votes

The response marshaling in spray is quite complex using the magnet pattern, which makes it very powerful and adjustable (e.g. by just adding an import of SprayJsonSupport automatically all JSON compatible case classes are valid responses).

A lot of the default resolutions do not work because one or the other implicit is missing. In this case, for futures to be working the ExecutionContext is missing. Try adding this to the Service:

private implicit def ec = actorRefFactory.dispatcher

Definitely give the linked article a read, helped me a lot of understanding spray better.