scala - 如何在 Play2.4/Scala 中自动订阅 actor 到 akka 事件总线

标签 scala playframework akka playframework-2.4

我开始深入研究 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)

一切都像以前一样编译和工作,没有任何记录。基本上, Actor 是不会被调用的。

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

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: No valid constructors[Module [events.modules.EventsRegistry] cannot be instantiated.]

我做错了什么?

更新 我得到这个工作的唯一方法是在 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....

最佳答案

要使其正常工作,您需要将注册表和模块分离。

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"

关于scala - 如何在 Play2.4/Scala 中自动订阅 actor 到 akka 事件总线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35073321/

相关文章:

function - 函数应用程序中未找到隐式参数

java - 在一个项目中混合 java、scala 和 xtend 文件?

java - Play 编译错误无法访问值 <root>.api 中的术语库。当前类路径可能缺少 <root>.api.libs 的定义,

scala - 在 scalaz 中违反了 Future monads 的左身份法

java - 如何在 Play Framework 中使用 Ebean 比较日期?

sql - 从 SQL 数据库中获取 Scala 中的一个值

java - 查找akka中所有 child Actor 的状态

java - Apache Flink 作业集群 rpc.address 绑定(bind)到 kubernetes 上的本地主机

java - 如何针对 Feed pull 优化 Tomcat

scala - 类 cats.data.Nested 中的方法映射无法识别