diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala index 87c9f9057f..e11890b21d 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala @@ -328,6 +328,34 @@ class ActorSelectionSpec extends AkkaSpec("akka.loglevel=DEBUG") with DefaultTim ActorSelection(c21, "../*/hello").toString must be(s"ActorSelection[Actor[akka://ActorSelectionSpec/user/c2/c21#${c21.path.uid}]/../*/hello]") } + "send ActorSelection targeted to missing actor to deadLetters" in { + val p = TestProbe() + system.eventStream.subscribe(p.ref, classOf[DeadLetter]) + system.actorSelection("/user/missing").tell("boom", testActor) + val d = p.expectMsgType[DeadLetter] + d.message must be("boom") + d.sender must be(testActor) + d.recipient.path.elements.mkString("/", "/", "") must be("/user/missing") + } + + "send ActorSelection wildcard targeted to missing actor to deadLetters" in { + val top = system.actorOf(p, "top") + top ! Create("child1") + top ! Create("child2") + + val probe = TestProbe() + system.eventStream.subscribe(probe.ref, classOf[DeadLetter]) + system.actorSelection("/user/top/*/a").tell("wild", testActor) + // wildcard matches both child1 and child2 + val d1 = probe.expectMsgType[DeadLetter] + val d2 = probe.expectMsgType[DeadLetter] + List(d1, d2) foreach { d ⇒ + d.message must be("wild") + d.sender must be(testActor) + d.recipient.path.elements.mkString("/", "/", "") must (equal("/user/top/child1/a") or equal("/user/top/child2/a")) + } + } + } } diff --git a/akka-actor/src/main/scala/akka/actor/ActorSelection.scala b/akka-actor/src/main/scala/akka/actor/ActorSelection.scala index 7b2b542dd8..8fec56e31d 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSelection.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSelection.scala @@ -147,9 +147,11 @@ object ActorSelection { rec(parent) case SelectChildName(name) ⇒ val child = refWithCell.getSingleChild(name) - if (child == Nobody) - sel.identifyRequest foreach { x ⇒ sender ! ActorIdentity(x.messageId, None) } - else if (iter.isEmpty) + if (child == Nobody) { + val emptyRef = new EmptyLocalActorRef(refWithCell.provider, anchor.path / sel.elements.map(_.toString), + refWithCell.underlying.system.eventStream) + emptyRef.tell(sel, sender) + } else if (iter.isEmpty) child.tell(sel.msg, sender) else rec(child) diff --git a/akka-remote/src/main/scala/akka/remote/RemoteDaemon.scala b/akka-remote/src/main/scala/akka/remote/RemoteDaemon.scala index 082c46b071..c023ee77f2 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteDaemon.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteDaemon.scala @@ -19,6 +19,7 @@ import akka.actor.SelectChildName import akka.actor.SelectChildPattern import akka.actor.Identify import akka.actor.ActorIdentity +import akka.actor.EmptyLocalActorRef /** * INTERNAL API @@ -141,7 +142,9 @@ private[akka] class RemoteSystemDaemon( } getChild(concatenatedChildNames.iterator) match { case Nobody ⇒ - sel.identifyRequest foreach { x ⇒ sender ! ActorIdentity(x.messageId, None) } + val emptyRef = new EmptyLocalActorRef(system.provider, path / sel.elements.map(_.toString), + system.eventStream) + emptyRef.tell(sel, sender) case child ⇒ child.tell(m, sender) }