简体   繁体   English

喷洒Akka Json Unmarshalling

[英]Spray Akka Json Unmarshalling

I've a problem about unmarshalling objects to Json via using spray - akka. 我有一个问题,通过使用spray - akka将对象解组到Json。

When i'd like to use actors that returns Future[List[Person]] , it doesn't work. 当我想使用返回Future [List [Person]]的actor时,它不起作用。

If i use dao object directly, it works. 如果我直接使用dao对象,它的工作原理。

Here are my codes: 这是我的代码:

PersonDao.scala 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 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 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 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 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 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)

}

When i run this code, It gives nothing and waits for a while. 当我运行这段代码时,它什么都没有,等待一段时间。

After waiting browser gives this message: 等待浏览器后发出以下消息:

The server was not able to produce a timely response to your request. 服务器无法及时响应您的请求。

And console output is 而控制台输出是

[ERROR] [11/22/2015 21:15:24.109] [actorSystem-akka.actor.default-dispatcher-7] [akka.actor.ActorSystemImpl(actorSystem)] Error during processing of request HttpRequest(GET, http://localhost:3001/person/,List(Host : localhost:3001, Connection: keep-alive, Cache-C ontrol: no-cache, Pragma: no-cache, User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.6.1000 Chrome/30.0.1599.101 Safari/537.36, DNT: 1, Accept-Encoding: gzip, deflate, Accept-Language: tr-TR),Empty,HTTP/1.1) akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://actorSystem/user/$a/entityServiceActor#-1810673919]] after [120000 ms]. [错误] [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),Empty,HTTP / 1.1 )akka.pattern.AskTimeoutException:在[120000 ms]之后询问[Actor [akka:// actorSystem / user / $ a / entityServiceActor#-1810673919]]的超时时间。 Sender[null] sent message of type "com.bilalalp.akkakafka.service.ServiceOperation$FIND_ALL$". 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) 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)

If i change PersonWebService.scala to this : 如果我将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)
        )
      }
    }
  }
}

It works and output is : 它的工作原理和输出是:

[{"id":1,"name":"Bilal","surname":"Alp"},{"id":2,"name":"Ahmet","surname":"Alp"}] [{ “ID”:1, “名称”: “比拉尔”, “姓”: “高山”},{ “ID”:2 “名称”: “艾哈迈德”, “姓”: “高山”}]

I'd like to use actors in spray routes. 我想在喷雾路线中使用演员。 I don't know whether it is a bad practice or not because i'm newbie in akka and spray. 我不知道这是不是一种坏习惯,因为我是akka和喷雾的新手。

How can i solve this? 我怎么解决这个问题? Any ideas? 有任何想法吗?

Thank you. 谢谢。

First of all, You can type ( PersonWebService.scala ): 首先,您可以键入( PersonWebService.scala ):

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

And as @Timothy Kim said You need to send back results using "sender ! getAll.onComplete 正如@Timothy Kim所说,你需要使用“sender!getAll.onComplete”发回结果

As I an see getAll returns Future, so in my opinion best would be to resolve it in EntityServiceActor.scala : 正如我看到getAll返回Future,所以在我看来最好是在EntityServiceActor.scala中解决它:

// 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

in this simple case getAll Future is resolved, if everything is ok, service will get list of persons, otherwise List will be empty. 在这个简单的情况下,getAll Future得到解决,如果一切正常,服务将获取人员列表,否则List将为空。

Oh and another thing PersonWebService.scala should have .mapTo[List[Person]] 哦,另一件事PersonWebService.scala应该有.mapTo [List [Person]]

You need to send a result back to sender: 您需要将结果发送回发件人:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM