将服务注入actor会产生NullPointerException



我不知道如何将服务注入Actor。

我尝试了几种方法,认为这一种最适合。

我认为主要的问题是,我将websocket作为参数提供给后续参与者。当我将Inject拉到类时,由于签名冲突,签名编译不执行。我尝试添加一个currying隐式类声明来注入服务,但也没有成功。

我该怎么做才能把它做好?

运行此代码会导致NullPointerException。

package actors
import akka.actor._
import com.google.inject.Inject
import play.api.libs.json._
import models._
import services.WeatherService
/**
* Created by jbc on 28.12.16.
*/
class WeatherWSActor (out: ActorRef) extends Actor {
@Inject() val weatherService: WeatherService = null
def handleMessage(msg: JsValue): JsValue = {
val req = msg.as[Request]
req match {
case Request("daily") => Json.toJson(weatherService.getFourDays())
case Request("next") => Json.toJson(weatherService.getNextHour())
}
}
override def receive: Receive = {
case msg: JsValue => out ! handleMessage(msg)
case _ => out ! "Bad Request"
}
@scala.throws[Exception](classOf[Exception])
override def postStop(): Unit = {
}
}
object WeatherWSActor {
def props(out: ActorRef) = Props(new WeatherWSActor(out))
}

控制器代码:

class WeatherWSController @Inject() (implicit system: ActorSystem, materializer: Materializer) extends Controller {
def socket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlow.actorRef(out => WeatherWSActor.props(out));
}
}

使用此模块代码设置服务

class Module extends AbstractModule {
override def configure(): Unit = {
bind(classOf[WeatherService]).to(classOf[WeatherServiceImpl]).asEagerSingleton()
}
}

这在文档中有所介绍,但这里有一个摘要。

如果你想注入你的演员,你需要改变一些事情。首先,注入点是构造函数,所以

class WeatherWSActor (out: ActorRef) extends Actor {
@Inject() val weatherService: WeatherService = null
// ...
}

应该成为

class WeatherWSActor @Inject() (out: ActorRef, 
weatherService: WeatherService) extends Actor {
// ...
}

事实上,将null分配给Scalaval也会给您带来问题。

其次,为参与者声明一个绑定,而不是自己创建它。

import com.google.inject.AbstractModule
import play.api.libs.concurrent.AkkaGuiceSupport
import actors.WeatherWSActor
class MyModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[WeatherWSActor]("weather-actor")
}
}

附带说明一下,您还需要为out创建一个命名绑定,并更改WeatherWSActor的定义以反映这一点:

class WeatherWSActor @Inject() (@javax.inject.Named("out-actor") out: ActorRef, 
weatherService: WeatherService) extends Actor {
// ...
}

out-actor是您在模块中设置的任何一个类,例如

class MyModule extends AbstractModule with AkkaGuiceSupport {
def configure = {
bindActor[WeatherWSActor]("weather-actor")
bindActor[SomeOutActor]("out-actor")
}
}

但是

由于在创建web套接字时您将获得out,因此(可能)您将拥有多个WeatherWSActor实例。这将影响如何处理依赖项注入,因此,不注入outActor(因此不为其创建绑定),而是使用一个向actor系统中某个点寻址的OutActor的所有实例广播的单例WeatherWSActor更有意义。

相关内容

最新更新