2017-01-04 2 views
0

Я не могу понять, как вводить Сервис в актера.инъекционная услуга для актера дает NullPointerException

Я опробовал несколько подходов и считаю, что этот должен соответствовать наилучшим образом.

Я думаю, что основная проблема заключается в том, что я предоставляю 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)) 
} 

Controller Код:

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

ответ

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 (и, следовательно, не создавать привязки для него), а скорее иметь singleton WeatherWSActor, который транслирует все экземпляры OutActor, адресованные в определенный момент в актерской системе.