Akkatype with classic actors giving me an error: Unsupported access to ActorContext from outside of Actor
Akkatype with classic actors giving me an error: Unsupported access to ActorContext from outside of Actor
我的 akka 应用程序(同时使用 akka typed 和 classic)出现以下运行时错误
java.lang.UnsupportedOperationException: Unsupported access to
ActorContext from the outside of
Actor[akka://my-classic-actor-system/user/ChatServer#1583147696]. No
message is currently processed by the actor, but ActorContext was
called from
Thread[my-classic-actor-system-akka.actor.default-dispatcher-5,5,run-main-group-0].
def main(args: Array[String]): Unit = {
val logger = LoggerFactory.getLogger(getClass)
logger.debug("Server starting yo...")
implicit val system = akka.actor.ActorSystem("my-classic-actor-system")
implicit val typedGuardian: ActorRef[Any] =
system.spawn(HttpWebsocketServer(), "ChatServer")
val client = system.actorOf(Client.props(remote), "clientActor")
//..
}
错误的来源是在 HttpWebsocketServer 内部,它取自 (
https://github.com/johanandren/chat-with-akka-http-websockets/blob/akka-2.6/src/main/scala/chat/Server.scala#L101):
object HttpWebsocketServer {
def apply(): Behavior[Any] = {
Behaviors.setup[Any] { context =>
implicit val ec: ExecutionContext = context.executionContext
val system = context.system
val chatRoom = context.spawn(ChatRoom(), "chat")
val userParent = context.spawn(SpawnProtocol(), "users")
val maker =
context.spawn(websock.Maker(), "mmaker")
val route =
path("chat") {
get {
handleWebSocketMessages(
newUserFlow(system, chatRoom, userParent)
)
}
}
// needed until Akka HTTP has a 2.6 only release
implicit val materializer: Materializer =
SystemMaterializer(context.system).materializer
implicit val classicSystem: akka.actor.ActorSystem =
context.system.toClassic
Http()
.bindAndHandle(route, "0.0.0.0", 9000)
// future callback, be careful not to touch actor state from in here
.onComplete {
case Success(binding) =>
context.log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
context.log.error("Server failed to start, terminating")
context.system.terminate()
}
Behaviors.empty
}
}
}
build.sbt
val AkkaVersion = "2.6.18"
val AkkaHttpVersion = "10.2.7"
libraryDependencies ++= Seq(
"io.netty" % "netty-all" % "4.1.68.Final",
"com.typesafe.akka" %% "akka-actor" % AkkaVersion,
"com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-stream" % AkkaVersion,
"com.typesafe.akka" %% "akka-stream-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion,
"ch.qos.logback" % "logback-classic" % "1.2.10",
scalaTest % Test
)
如果我在我的代码中注释掉下面的内容,我不会收到运行时错误,所以看起来这就是问题的根源:
implicit val materializer: Materializer =
SystemMaterializer(context.system).materializer
implicit val classicSystem: akka.actor.ActorSystem =
context.system.toClassic
Http()
.bindAndHandle(route, "0.0.0.0", 9000)
// future callback, be careful not to touch actor state from in here
.onComplete {
case Success(binding) =>
context.log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
context.log.error("Server failed to start, terminating")
context.system.terminate()
}
我不确定我能做些什么来解决这个问题,我正在从系统或子演员中创建演员。
您不能在 actor 之外使用 context
。你这样做是为了回想你的未来。
case Success(binding) =>
context.log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
context.log.error("Server failed to start, terminating")
context.system.terminate()
问题是 actor 上下文被视为 actor 的内部状态,不能在范围之外访问。连你的评论都这么说
// future callback, be careful not to touch actor state from in here
解决方案是在回调之外的 val
中预先引用您的 log
和 system
(您已经有了)。回调看起来像
case Success(binding) =>
log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
log.error("Server failed to start, terminating")
system.terminate()
我的 akka 应用程序(同时使用 akka typed 和 classic)出现以下运行时错误
java.lang.UnsupportedOperationException: Unsupported access to ActorContext from the outside of Actor[akka://my-classic-actor-system/user/ChatServer#1583147696]. No message is currently processed by the actor, but ActorContext was called from Thread[my-classic-actor-system-akka.actor.default-dispatcher-5,5,run-main-group-0].
def main(args: Array[String]): Unit = {
val logger = LoggerFactory.getLogger(getClass)
logger.debug("Server starting yo...")
implicit val system = akka.actor.ActorSystem("my-classic-actor-system")
implicit val typedGuardian: ActorRef[Any] =
system.spawn(HttpWebsocketServer(), "ChatServer")
val client = system.actorOf(Client.props(remote), "clientActor")
//..
}
错误的来源是在 HttpWebsocketServer 内部,它取自 ( https://github.com/johanandren/chat-with-akka-http-websockets/blob/akka-2.6/src/main/scala/chat/Server.scala#L101):
object HttpWebsocketServer {
def apply(): Behavior[Any] = {
Behaviors.setup[Any] { context =>
implicit val ec: ExecutionContext = context.executionContext
val system = context.system
val chatRoom = context.spawn(ChatRoom(), "chat")
val userParent = context.spawn(SpawnProtocol(), "users")
val maker =
context.spawn(websock.Maker(), "mmaker")
val route =
path("chat") {
get {
handleWebSocketMessages(
newUserFlow(system, chatRoom, userParent)
)
}
}
// needed until Akka HTTP has a 2.6 only release
implicit val materializer: Materializer =
SystemMaterializer(context.system).materializer
implicit val classicSystem: akka.actor.ActorSystem =
context.system.toClassic
Http()
.bindAndHandle(route, "0.0.0.0", 9000)
// future callback, be careful not to touch actor state from in here
.onComplete {
case Success(binding) =>
context.log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
context.log.error("Server failed to start, terminating")
context.system.terminate()
}
Behaviors.empty
}
}
}
build.sbt
val AkkaVersion = "2.6.18"
val AkkaHttpVersion = "10.2.7"
libraryDependencies ++= Seq(
"io.netty" % "netty-all" % "4.1.68.Final",
"com.typesafe.akka" %% "akka-actor" % AkkaVersion,
"com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-stream" % AkkaVersion,
"com.typesafe.akka" %% "akka-stream-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion,
"ch.qos.logback" % "logback-classic" % "1.2.10",
scalaTest % Test
)
如果我在我的代码中注释掉下面的内容,我不会收到运行时错误,所以看起来这就是问题的根源:
implicit val materializer: Materializer =
SystemMaterializer(context.system).materializer
implicit val classicSystem: akka.actor.ActorSystem =
context.system.toClassic
Http()
.bindAndHandle(route, "0.0.0.0", 9000)
// future callback, be careful not to touch actor state from in here
.onComplete {
case Success(binding) =>
context.log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
context.log.error("Server failed to start, terminating")
context.system.terminate()
}
我不确定我能做些什么来解决这个问题,我正在从系统或子演员中创建演员。
您不能在 actor 之外使用 context
。你这样做是为了回想你的未来。
case Success(binding) =>
context.log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
context.log.error("Server failed to start, terminating")
context.system.terminate()
问题是 actor 上下文被视为 actor 的内部状态,不能在范围之外访问。连你的评论都这么说
// future callback, be careful not to touch actor state from in here
解决方案是在回调之外的 val
中预先引用您的 log
和 system
(您已经有了)。回调看起来像
case Success(binding) =>
log.debug(
s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
)
case Failure(ex) =>
ex.printStackTrace()
log.error("Server failed to start, terminating")
system.terminate()