将服务注入到actor中会产生NullPointerException

时间:2017-01-04 08:11:05

标签: scala web-services guice actor playframework-2.5

我无法弄清楚如何将服务注入演员。

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

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

我该怎样做才能做到正确?

运行此代码会导致NullPointerException。

buildTemplate()

控制器代码:

buildOriginal()

使用此模块代码

设置服务
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))
}

1 个答案:

答案 0 :(得分:0)

documentation中介绍了这一点,但这里是摘要。

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

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

应该成为

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

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

其次,为演员声明一个绑定而不是自己创建它。

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")
  }
}

<强>可是...

由于您在创建网络套接字时获得out,因此您(可能)会有多个WeatherWSActor个实例。这将影响你如何处理依赖注入,所以不注入outActor(因此不为它创建绑定)更有意义,而是有一个单例WeatherWSActor向所有人广播OutActor的实例在演员系统中的某个点处解决。