Scala 注入Akka Actor以使用Guice播放Framework 2.5失败
我试图在Play 2.5应用程序中使用Akka actor,并使用依赖项注入。我基本上遵循了,下面是我的代码: 演员 基本上,我有一个简单的actor,它接收一些数据,处理数据,然后将数据发送回调用方Scala 注入Akka Actor以使用Guice播放Framework 2.5失败,scala,dependency-injection,akka,playframework-2.5,Scala,Dependency Injection,Akka,Playframework 2.5,我试图在Play 2.5应用程序中使用Akka actor,并使用依赖项注入。我基本上遵循了,下面是我的代码: 演员 基本上,我有一个简单的actor,它接收一些数据,处理数据,然后将数据发送回调用方 package actors import akka.actor._ import akka.pattern.{AskTimeoutException, ask} import akka.util.Timeout import javax.inject._ import com.goo
package actors
import akka.actor._
import akka.pattern.{AskTimeoutException, ask}
import akka.util.Timeout
import javax.inject._
import com.google.inject.assistedinject.Assisted
import play.api.Configuration
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
object ServiceActor {
val ConfigKey = "actors.path" // remote actor path
trait Factory {
def apply(key: String): Actor
}
}
class ServiceActor @Inject()(configuration: Configuration,
actorSystem: ActorSystem,
@Assisted key: String)
(implicit val ec: ExecutionContext)
extends Actor {
import ServiceActor._
implicit val timeout = Timeout(5.minutes)
def receive = {
case data: SomeData => sender ! someFunction(data)
}
// implemented in the real code, omitted because not important for the question
def someFunction = ???
}
模块
根据文档,我需要制作一个简单的模块,并激活它。以下是模块:
package modules
import com.google.inject.AbstractModule
import play.api.libs.concurrent.AkkaGuiceSupport
import actors.ServiceActor
class ServiceModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[ServiceActor]("service-actor")
}
}
然后我通过在application.conf
中添加以下行来激活此模块:
play.modules {
enabled += modules.ServiceModule
}
控制器
最后,我尝试在控制器中使用参与者:
package controllers
import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import javax.inject._
import play.api.mvc._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
@Singleton
class SearchController @Inject()(@Named("service-actor") serviceActor: ActorRef)
(implicit ec: ExecutionContext)
extends Controller {
implicit val timeout = Timeout(5.minutes)
def search(param: String) = Action.async {
val request = SomeRequestType(param)
(serviceActor ? request).mapTo[SomeResponseType] map { result =>
Ok(result.toString)
}
}
}
据我所知,我完全按照文档进行了操作,但打电话给控制器时会出现以下错误:
[AskTimeoutException: Recipient[Actor[akka://application/user/service-actor#-366470383]]
had already been terminated.
Sender[null] sent the message of type "some.namespace.SomeRequestType".]
据我所知,错误是关于参与者如何为null
,我们无法向其发送消息。虽然错误代码说“已经终止”,但看起来演员一开始就没有被启动过
我不确定首先应该看哪里,我做错了什么,因为我没有使用Guice的经验
问题是,我做错了什么?为什么演员没有发起,或者如果它确实已经被终止,为什么它被终止?我该如何解决这个问题
非常感谢。希望您已经解决了这个问题。然而,我仍然在这里张贴答案,仅供一些新来者参考,因为我花了一段时间才找出这个问题的原因 据我所知,错误在于参与者如何为空,我们无法向其发送消息。 不完全是。问模式?具有sender的隐式参数,默认为ActorRef.noSender,源代码为 通常,如果你在一个参与者中,你在一个称为self的作用域中有一个隐式ActorRef,但是因为你不在参与者中,所以它只是取默认值 虽然错误代码说“已经终止”,但看起来演员一开始就没有被启动过。 对。最有可能的是,你的演员从一开始就没有被正确引导过。在您的控制台中,您应该看到比从Play网页的响应中看到的更多的错误消息 例如,下面是我在得到AskTimeoutException之前实际得到的错误
1 error
akka.actor.ActorInitializationException: akka://application/user/user-actor: exception during creation
at akka.actor.ActorInitializationException$.apply(Actor.scala:193)
at akka.actor.ActorCell.create(ActorCell.scala:608)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:462)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:484)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:282)
at akka.dispatch.Mailbox.run(Mailbox.scala:223)
at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
Caused by: com.google.inject.ConfigurationException: Guice configuration errors:
总而言之,您可能需要再次检查sbt控制台和注入,以确保首先启动了参与者。您的用例是否足够简单,可以消除Guice而只使用javax.inject?