找不到 ActorSystem 的隐式值
Could not find implicit value for ActorSystem
我刚开始使用 Akka 和 Scala,我正在尝试使用 Akka Streams 连接到 WebSocket。我在下面创建了 SocketActor
并尝试从 main 方法实例化。
这是我的 SocketActor
:
package com.lightbend.akka.sample
import akka.actor.{Actor, Props}
import akka.Done
import akka.http.scaladsl.Http
import akka.stream.scaladsl._
import akka.http.scaladsl.model.ws._
import scala.concurrent.Future
object SocketActor {
def props(coinApiIdentifier: String): Props = Props(new SocketActor(coinApiIdentifier))
case object Start
case object Stop
}
class SocketActor(val ticker: String) extends Actor {
import SocketActor._
// Future[Done] is the materialized value of Sink.foreach,
// emitted when the stream completes
private val incoming: Sink[Message, Future[Done]] =
Sink.foreach[Message] {
case message: TextMessage.Strict =>
println(message.text)
}
// send this as a message over the WebSocket
private val outgoing = Source.single(TextMessage("hello world!"))
// flow to use (note: not re-usable!)
private val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("wss://api.com/v1/"))
// the materialized value is a tuple with
// upgradeResponse is a Future[WebSocketUpgradeResponse] that
// completes or fails when the connection succeeds or fails
// and closed is a Future[Done] with the stream completion from the incoming sink
private val graph =
outgoing
.viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse]
.toMat(incoming)(Keep.both) // also keep the Future[Done]
override def receive: PartialFunction[Any, Unit] = {
case Start =>
println("Start message received.")
graph.run()
}
}
还有我的主要方法:
object AkkaQuickstart extends App {
// Create the 'helloAkka' actor system
val system: ActorSystem = ActorSystem("test")
val materializer: ActorMaterializer = ActorMaterializer()
val socketActor: ActorRef =
system.actorOf(SocketActor.props("hello"), "socket-actor")
socketActor ! Start
}
不幸的是,我得到了错误:
Error:(38, 35) could not find implicit value for parameter system:
akka.actor.ActorSystem private val webSocketFlow =
Http().webSocketClientFlow(WebSocketRequest("wss://api.com/v1/"))
我试过将一些 implicit
参数传递给 SocketActor
的构造函数,但效果不佳。由于某种原因,ActorSystem
似乎不在范围内。如何让我的 system
进入 SocketActor
中的 Http()
函数?
定义隐式 val
:
class SocketActor(val ticker: String) extends Actor {
implicit val sys = context.system
// ...
}
这将提供 Http
对象所期望的隐式 ActorSystem
。
您的代码还有另一个问题:您的 actor 中的流不会 运行 因为范围内没有物化器。解决这个问题的一种方法是在 actor 内部创建物化器:
class SocketActor(val ticker: String) extends Actor {
implicit val sys = context.system
implicit val mat = ActorMaterializer()(context)
// ...
}
请注意,如果实体化器定义为 implicit val mat = ActorMaterializer()
,由于 implicit val sys = context.system
,它会隐式使用 context.system
。相反,实体化器是使用 actor 的 context
显式创建的。这样做是因为 documentation:
中的警告
Do not create new actor materializers inside actors by passing the context.system
to it. This will cause a new ActorMaterializer
to be created and potentially leaked (unless you shut it down explicitly) for each such actor. It is instead recommended to either pass-in the Materializer or create one using the actor’s context
.
允许 actor 的创建者重用 materializer 的推荐方法是将 materializer 作为隐式参数传递给 actor:
class SocketActor(val ticker: String)(implicit val mat: ActorMaterializer) extends Actor {
implicit val sys = context.system
// ...
}
那你可以把主程序中的materializer传给这个actor:
object AkkaQuickstart extends App {
implicit val system: ActorSystem = ActorSystem("test")
implicit val materializer: ActorMaterializer = ActorMaterializer()
val socketActor: ActorRef =
system.actorOf(Props(classOf[SocketActor], "hello", materializer), "socket-actor")
socketActor ! Start
}
我刚开始使用 Akka 和 Scala,我正在尝试使用 Akka Streams 连接到 WebSocket。我在下面创建了 SocketActor
并尝试从 main 方法实例化。
这是我的 SocketActor
:
package com.lightbend.akka.sample
import akka.actor.{Actor, Props}
import akka.Done
import akka.http.scaladsl.Http
import akka.stream.scaladsl._
import akka.http.scaladsl.model.ws._
import scala.concurrent.Future
object SocketActor {
def props(coinApiIdentifier: String): Props = Props(new SocketActor(coinApiIdentifier))
case object Start
case object Stop
}
class SocketActor(val ticker: String) extends Actor {
import SocketActor._
// Future[Done] is the materialized value of Sink.foreach,
// emitted when the stream completes
private val incoming: Sink[Message, Future[Done]] =
Sink.foreach[Message] {
case message: TextMessage.Strict =>
println(message.text)
}
// send this as a message over the WebSocket
private val outgoing = Source.single(TextMessage("hello world!"))
// flow to use (note: not re-usable!)
private val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("wss://api.com/v1/"))
// the materialized value is a tuple with
// upgradeResponse is a Future[WebSocketUpgradeResponse] that
// completes or fails when the connection succeeds or fails
// and closed is a Future[Done] with the stream completion from the incoming sink
private val graph =
outgoing
.viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse]
.toMat(incoming)(Keep.both) // also keep the Future[Done]
override def receive: PartialFunction[Any, Unit] = {
case Start =>
println("Start message received.")
graph.run()
}
}
还有我的主要方法:
object AkkaQuickstart extends App {
// Create the 'helloAkka' actor system
val system: ActorSystem = ActorSystem("test")
val materializer: ActorMaterializer = ActorMaterializer()
val socketActor: ActorRef =
system.actorOf(SocketActor.props("hello"), "socket-actor")
socketActor ! Start
}
不幸的是,我得到了错误:
Error:(38, 35) could not find implicit value for parameter system: akka.actor.ActorSystem private val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("wss://api.com/v1/"))
我试过将一些 implicit
参数传递给 SocketActor
的构造函数,但效果不佳。由于某种原因,ActorSystem
似乎不在范围内。如何让我的 system
进入 SocketActor
中的 Http()
函数?
定义隐式 val
:
class SocketActor(val ticker: String) extends Actor {
implicit val sys = context.system
// ...
}
这将提供 Http
对象所期望的隐式 ActorSystem
。
您的代码还有另一个问题:您的 actor 中的流不会 运行 因为范围内没有物化器。解决这个问题的一种方法是在 actor 内部创建物化器:
class SocketActor(val ticker: String) extends Actor {
implicit val sys = context.system
implicit val mat = ActorMaterializer()(context)
// ...
}
请注意,如果实体化器定义为 implicit val mat = ActorMaterializer()
,由于 implicit val sys = context.system
,它会隐式使用 context.system
。相反,实体化器是使用 actor 的 context
显式创建的。这样做是因为 documentation:
Do not create new actor materializers inside actors by passing the
context.system
to it. This will cause a newActorMaterializer
to be created and potentially leaked (unless you shut it down explicitly) for each such actor. It is instead recommended to either pass-in the Materializer or create one using the actor’scontext
.
允许 actor 的创建者重用 materializer 的推荐方法是将 materializer 作为隐式参数传递给 actor:
class SocketActor(val ticker: String)(implicit val mat: ActorMaterializer) extends Actor {
implicit val sys = context.system
// ...
}
那你可以把主程序中的materializer传给这个actor:
object AkkaQuickstart extends App {
implicit val system: ActorSystem = ActorSystem("test")
implicit val materializer: ActorMaterializer = ActorMaterializer()
val socketActor: ActorRef =
system.actorOf(Props(classOf[SocketActor], "hello", materializer), "socket-actor")
socketActor ! Start
}