首页 文章

喷洒Akka Json Unmarshalling

提问于
浏览
4

我有一个问题,通过使用spray - akka将对象解组到Json .

当我想使用返回Future [List [Person]]的actor时,它不起作用 .

如果我直接使用dao对象,它的工作原理 .

这是我的代码:

PersonDao.scala

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

case class Person(id: Int, name: String, surname: String)

object PersonDao {

  def getAll: Future[List[Person]] = Future {
    List[Person](Person(1, "Bilal", "Alp"), Person(2, "Ahmet", "Alp"))
  }
}

EntityServiceActor.scala

import akka.actor.Actor
import com.bilalalp.akkakafka.model.PersonDao
import com.bilalalp.akkakafka.service.ServiceOperation.FIND_ALL

object ServiceOperation {

  case object FIND_ALL

}

class EntityServiceActor extends Actor {

  override def receive: Receive = {

    case FIND_ALL => PersonDao.getAll
  }
}

ServerSupervisor.scala

import akka.actor.{Actor, ActorRefFactory}
import com.bilalalp.akkakafka.webservice.TaskWebService
import spray.routing.RejectionHandler.Default


class ServerSupervisor extends Actor with PersonWebService {

  implicit val system = context.system

  override def receive: Receive = runRoute(entityServiceRoutes)

  override implicit def actorRefFactory: ActorRefFactory = context
}

WebServiceTrait.scala

import akka.util.Timeout

import spray.routing.HttpService

import scala.concurrent.duration._
import scala.language.postfixOps

import org.json4s.NoTypeHints
import org.json4s.native.Serialization._

trait WebServiceTrait extends HttpService {

  implicit def executionContext = actorRefFactory.dispatcher

  implicit val json4sFormats = formats(NoTypeHints)

  implicit val timeout = Timeout(120 seconds)
}

PersonWebService.scala

trait PersonWebService extends WebServiceTrait with Json4sSupport {

  val json3sFormats = DefaultFormats

  val entityServiceWorker = actorRefFactory.actorOf(Props[EntityServiceActor], "entityServiceActor")

  val entityServiceRoutes = {
    pathPrefix("person") {
      pathEndOrSingleSlash {
        get {
          ctx => ctx.complete((entityServiceWorker ? FIND_ALL).mapTo[Person])
        }
      }
    }
  }
}

Application.scala

import akka.actor.{ActorRef, ActorSystem, Props}
import akka.io.IO
import com.bilalalp.akkakafka.server.ServerSupervisor
import spray.can.Http


object Application extends App {

  implicit val system = ActorSystem("actorSystem")

  val mainHandler: ActorRef = system.actorOf(Props[ServerSupervisor])
  IO(Http)! Http.Bind(mainHandler, interface = Configuration.appInterface, port = Configuration.appPort)

}

当我运行这段代码时,它什么都没有,等待一段时间 .

等待浏览器后发出以下消息:

服务器无法及时响应您的请求 .

而控制台输出是

[ERROR] [11/22/2015 21:15:24.109] [actorSystem-akka.actor.default-dispatcher-7] [akka.actor.ActorSystemImpl(actorSystem)]处理请求HttpRequest时出错(GET,http: // localhost:3001 / person /,List(主机:localhost:3001,连接:keep-alive,Cache-C ontrol:no-cache,Pragma:no-cache,User-Agent:Mozilla / 5.0(Windows NT 6.3; WOW64)AppleWebKit / 537.36(KHTML,如Gecko)Maxthon / 4.4.6.1000 Chrome / 30.0.1599.101 Safari / 537.36,DNT:1,Accept-Encoding:gzip,deflate,Accept-Language:tr-TR),空,HTTP / 1.1)akka.pattern.AskTimeoutException:在[120000 ms]之后询问[Actor [akka:// actorSystem / user / $ a / entityServiceActor#-1810673919]]的超时时间 . Sender [null]发送了“com.bilalalp.akkakafka.service.ServiceOperation $ FIND_ALL $”类型的消息 . at akka.pattern.PromiseActorRef $$ anonfun $ 1.apply $ mcV $ sp(AskSupport.scala:415)at akka.actor.Scheduler $$ anon $ 7.run(Scheduler.scala:132)at scala.concurrent.Future $ InternalCallbackExecutor $ .unbatchedExecute(Future.scala:599)at scala.concurrent.BatchingExecutor $ class.execute(BatchingExecutor.scala:109)at scala.concurrent.Future $ InternalCallbackExecutor $ .execute(Future.scala:597)

如果我将PersonWebService.scala更改为:

trait PersonWebService extends WebServiceTrait with Json4sSupport {

  val json3sFormats = DefaultFormats

  val entityServiceWorker = actorRefFactory.actorOf(Props[EntityServiceActor], "entityServiceActor")

  val entityServiceRoutes = {
    pathPrefix("person") {
      pathEndOrSingleSlash {
        get (
//                    ctx => ctx.complete((entityServiceWorker ? FIND_ALL).mapTo[Person])
          ctx => ctx.complete(PersonDao getAll)
        )
      }
    }
  }
}

它的工作原理和输出是:

[{“id”:1,“name”:“Bilal”,“surname”:“Alp”},{“id”:2,“name”:“Ahmet”,“surname”:“Alp”}]

我想在喷雾路线中使用演员 . 我不知道这是不是一种坏习惯,因为我是akka和喷雾的新手 .

我怎么解决这个问题?有任何想法吗?

谢谢 .

2 回答

  • 4

    首先,您可以输入( PersonWebService.scala ):

    pathEndOrSingleSlash {
        get {
          complete {
           (entityServiceWorker ? FindAll).mapTo[List[Person]]
        }
      }
    

    正如@Timothy Kim所说,你需要使用“sender!getAll.onComplete”发回结果

    正如我看到getAll返回Future,所以在我看来最好是在_952753中解决它:

    // import the pipe pattern (see pipeTo below):
    import akka.pattern.pipe
    import context.dispatcher
    
    override def receive: Receive = {
      case FindAll => 
        PersonDao.getAll()
          .recover({ case err => List() /* could log error here */ })
          .pipeTo(sender()) // do this instead of onComplete, it's safer
    

    在这个简单的情况下,getAll Future得到解决,如果一切正常,服务将获得人员列表,否则List将为空 .

    哦,另一件事 PersonWebService.scala 应该有 .mapTo[List[Person]]

  • 3

    您需要将结果发送回发件人:

    case FIND_ALL =>
      PersonDao.getAll.pipeTo(sender())
    

相关问题