How to select akka actor with actorSelection?

Cherry picture Cherry · Oct 24, 2014 · Viewed 11.9k times · Source

I am trying to select one actor which have already created. Here is a code:

val myActor = system.actorOf(Props(classOf[MyActor]), "myActorName")
println("myActor path - " + akka.serialization.Serialization.serializedActorPath(myActor))
println("Selection from spec akka://unit-test/user/myActorName " + system.actorSelection("akka://unit-test/user/myActorName").resolveOne().value)
println("Selection from spec /user/myActorName/ " + system.actorSelection("/user/myActorName/").resolveOne().value)

The result is:

myActor path - akka.tcp://[email protected]:46635/user/myActorName#1444872428
Selection from spec akka://unit-test/user/myActorName None
Selection from spec /user/myActorName/ None

Also I can pass a message to actor and it completes well. What I missed during actorSelection? How to select actor properly?

UPDATED

It is very strange, but when I replace system.actorSelection("/user/myActorName/").resolveOne().value with system.actorFor("/user/myActorName/") everything works. I mean actorFor returns an actor. (Which is not a right solution due to actorFor is deprecated)

Answer

dk14 picture dk14 · Oct 24, 2014

Please, be careful with futures. In your case you're receiving future which may be not completed at the calling moment - so its value may be empty:

scala> println("Selection from spec /user/myActorName/ " +   system.actorSelection("/user/myActorName/").resolveOne().value)
Selection from spec /user/myActorName/ None

vs

scala> val fut =   system.actorSelection("/user/myActorName/").resolveOne()
fut: scala.concurrent.Future[akka.actor.ActorRef] = scala.concurrent.impl.Promise$DefaultPromise@7eb8d7bd

<just wait some time here>

scala> fut.value
res21: Option[scala.util.Try[akka.actor.ActorRef]] = Some(Success(Actor[akka://default/user/myActorName#1625966960]))

To obtain value correctly use onComplete or just for-comprehesion/map:

import scala.concurrent.ExecutionContext.Implicits.global

for (res <- system.actorSelection("/user/myActorName").resolveOne()) {
   println(res)
}

Keep in mind that onComplete/for are implemented as listeners, so they might be executed in different thread. If you need the result in current thread - use classical Await.result (it's blocking - so, you should do it outside of actor's context/receive).