2017-01-04 17 views
0

サービスをアクタに挿入する方法がわかりません。アクターにサービスを注入するとNullPointerExceptionが発生します

私はいくつかのアプローチを試してみましたが、これは一番合うと思います。

私は、パラメータとして次のアクターにwebsocketを提供することが大きな問題だと思います。 Injectをクラス・シグネチャにプルすると、シグネチャの競合が原因でコンパイルが実行されません。 サービスを注入するために暗黙のクラス宣言を追加しようとしましたが、これもうまくいきませんでした。

正しくするにはどうすればよいですか?

このコードを実行すると、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() 
    } 
} 

答えて

0

これはdocumentationで覆われているが、ここで要約だと設定されています。

アクターを挿入する場合は、いくつか変更する必要があります。まず第一に、注入点はとても

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

はScalaのvalnullを割り当て、実際には

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

になる必要がありますまた、あなたの問題を与えるために起こっている、コンストラクタです。

第2に、俳優のためのバインディングを自分で作成する代わりに宣言します。サイドノートでは

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のすべてのインスタンスにブロードキャストされます俳優のシステムで。

関連する問題