Reputation: 3485
I am creating an actor and I want to create it the first time and then use its actor reference whenever that actor is needed. Here is the code
val actorPath = "akka://testActorSystem/user/'"
object ActorManager {
def getTestActorRef: ActorRef = {
var actorRef: Option[ActorRef] = None
this.synchronized {
val sel = system.actorSelection(actorPath + "testActor");
val future1 = sel.resolveOne()
val res: Try[ActorRef] = Await.ready(future1, timeout.duration).value.get
res match {
case Success(actorref) =>
actorRef = Some(actorref)
actorRef.get
case Failure(e) =>
val testActor = system.actorOf(Props[TestActor], name = "testActor")
actorRef = Some(testActor)
}
getActorRef(actorRef.get)
}
actorRef.get
}
}
Q1->Is that the right way to achieve my desired functionality? The problem I am having is whenever this code is called in two places at the same time.
ActorManager.getTestActorRef
it throws two different exceptions:
akka.actor.ActorNotFound: Actor not found for: ActorSelection[Anchor(akka://testActorSystem/), Path(/user/'testActor)]
at akka.actor.ActorSelection$$anonfun$resolveOne$1.apply(ActorSelection.scala:65) ~[akka-actor_2.11-2.3.6.jar:na]
at akka.actor.ActorSelection$$anonfun$resolveOne$1.apply(ActorSelection.scala:63) ~[akka-actor_2.11-2.3.6.jar:na]
and:
akka.actor.InvalidActorNameException: actor name [testActor] is not unique!
at akka.actor.dungeon.ChildrenContainer$NormalChildrenContainer.reserve(ChildrenContainer.scala:130) ~[akka-actor_2.11-2.3.6.jar:na]
at akka.actor.dungeon.Children$class.reserveChild(Children.scala:77) ~[akka-actor_2.11-2.3.6.jar:na]
at akka.actor.ActorCell.reserveChild(ActorCell.scala:369) ~[akka-actor_2.11-2.3.6.jar:na]
I tried to use this.synchronized
but it did not help, the problem arises when I am invoking this method more than once
ActorManager.getTestActorRef
How can I create actor once and use its actorRef again and again without creating it again?
Upvotes: 0
Views: 305
Reputation: 1770
To achieve your goal you just need:
object ActorManager {
val getTestActorRef: ActorRef = system.actorOf(Props[TestActor], name = "testActor")
}
this will create actor once and it will be available. You do not need all these thing with actorSelection, synchronized and so on.
So you will get static reference to ActorRef you can use to send messages. Actor for this reference will be created once in background.
Upvotes: 3