【问题标题】:How to subscribe actors into akka event bus automatically in Play2.4/Scala如何在 Play2.4/Scala 中自动将参与者订阅到 akka 事件总线
【发布时间】:2016-05-06 12:39:05
【问题描述】:

我开始深入研究 AKKA/Event Bus 和相关...

我创建了一个小的测试actor如下:

class TestActor extends Actor with ClassLogger{


    @throws[Exception](classOf[Exception])
    override def preStart(): Unit = {
        context.system.eventStream.subscribe(context.self, classOf[FormFieldValue])
    }

    override def receive = {
        case (v: FormFieldValue) => logger.info("Value received: " + v.fieldValue)
        case _ => logger.info("Something unknown")
    }
}

并尝试从应用程序的另一部分发布事件:

system.eventStream.publish(updatedValue)

一切都像以前一样编译和工作,没有任何记录。基本上,演员没有被调用。

现在,我还尝试创建一个将注册所有订阅者的模块,如下所示:

class EventsRegistry @Inject()(system: ActorSystem) extends AbstractModule {

    override def configure(): Unit = {
        val testListeener = system.actorOf(Props(classOf[TestActor]))

        system.eventStream.subscribe(testListeener, classOf[FormFieldValue])
    }
}

并在application.conf中配置模块:

play.modules.enabled  += "events.modules.EventsRegistry"

并从 Actor 中移除 preStart。

现在我收到一个错误:

lay.api.PlayException: 没有有效的构造函数[模块 [events.modules.EventsRegistry] 无法实例化。]

我做错了什么?

更新 我得到这个工作的唯一方法是在 Global#onStart 中设置订阅者:

override def onStart(app: play.api.Application) {

        val testListeener = Akka.system.actorOf(Props(classOf[TestActor]))

        Akka.system.eventStream.subscribe(testListeener, classOf[FormFieldValue])

    }

但不推荐使用 GlobalSettings....

【问题讨论】:

    标签: scala playframework akka playframework-2.4


    【解决方案1】:

    要使其工作,您需要将注册表和模块解耦。

    package actors
    import akka.actor._
    import com.google.inject._
    import play.api.inject.ApplicationLifecycle
    
    import scala.concurrent.Future
    
    case class FormFieldValue(fieldValue: String)
    
    class TestActor extends Actor with ActorLogging {
    
      @throws[Exception](classOf[Exception])
      override def preStart(): Unit = {
        context.system.eventStream.subscribe(context.self, classOf[FormFieldValue])
        super.preStart()
      }
    
      @throws[Exception](classOf[Exception])
      override def postStop(): Unit = {
        context.system.eventStream.unsubscribe(context.self)
        super.postStop()
      }
    
      override def receive = {
        case (v: FormFieldValue) => log.info("Value received: " + v.fieldValue)
        case _ => log.info("Something unknown")
      }
    }
    
    @Singleton
    class EventBusLifeCycle @Inject()(system: ActorSystem, lifecycle: ApplicationLifecycle) {
      val testListener = system.actorOf(Props(classOf[TestActor]))
    
      lifecycle.addStopHook { () =>
        Future.successful(system.stop(testListener))
      }
    
    }
    
    class EventBusModule extends AbstractModule {
      def configure() = {
        bind(classOf[EventBusLifeCycle]).asEagerSingleton()
      }
    }
    

    并在application.conf中注册模块

    play.modules.enabled += "actors.EventBusModule"
    

    【讨论】:

    • Play 无法将 ActorSystem 注入到 Module 类。这个答案解决了这个问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多