How to get an ActorRef from "this" - scala

Lets say you have an actor class:
class MyActor extends Actor { }
And somewhere within MyActor, you'd like to pass it to another actor. But, you need "this" as an ActorRef. Since "this" is of type Actor, it can not be passed where ActorRef is required.
So the question is, how can an Actor ("this") get a reference to itself as an ActorRef? Is this even possible, or am I totally misunderstanding something...

From an Actor you can use self to get the ActorRef

If you know the path of an actor and you want to know its ActorRef then you can obtain it. You just have to create an actor using the actor selection and then send an Identity(none) message to that actor. It will send its ActorRefas a reply.
You find a more detailed explanation here: https://doc.akka.io/docs/akka/snapshot/actors.html

Related

this vs self inside akka actor class

Let's say I have a very simple actor class which receives any message and prints to the console.
class SimpleActor extends Actor{
def receive: Receive = {
case message =>
println(s"[${this}][${self}] received message: ${message}")
}
}
val simpleActor = actorSystem.actorOf(Props[SimpleActor], "simpleActor")
simpleActor ! "Hey"
As you can see I am using both this and self here and both has different values. Its output is something like:
[pkg.ActorRunner$SimpleActor#65cca69][Actor[akka://ActorDemo/user/simpleActor#934141660]] received message: Hey
I want to understand the difference between self and this because in complex scenarios(production system) if the actor breaks, for example: throws an exception than I think value for this gets changed.
this is classic java reference to the object extending Actor trait while self is a reference to the ActorRef that is what you need to send messages (! or tell and ? or ask)
You can't send messages to this
You shouldn't pass reference to this outside actor while passing reference to self is perfectly fine, in fact it is sent implicitly when you send a message to an actor from another actor. If you pass this to another object you will be risking actor's state encapsulation. Remember that the only way to communicate with an actor is via messages, i.e. with its ActorRef
self will remain valid after actor restart, aka you can keep sending messages to the same ActorRef (self). Only when the actor is stopped the reference to ActorRef is no longer valid and messages sent to that address will end in Dead Letters.
this will no longer be valid after actor restart. A new object of type Actor is instantiated to clear the actor state that could be compromised due to failure.
What restarting means
Unless the failure is specifically recognizable, the third cause cannot be ruled out, which leads to the conclusion that the internal state needs to be cleared out. If the supervisor decides that its other children or itself is not affected by the corruption—e.g. because of conscious application of the error kernel pattern—it is therefore best to restart the child. This is carried out by creating a new instance of the underlying Actor class and replacing the failed instance with the fresh one inside the child’s ActorRef; the ability to do this is one of the reasons for encapsulating actors within special references. The new actor then resumes processing its mailbox, meaning that the restart is not visible outside of the actor itself with the notable exception that the message during which the failure occurred is not re-processed.
Actor Reference and Path Equality
Note that a restart of an actor caused by a failure still means that it is the same actor incarnation, i.e. a restart is not visible for the consumer of the ActorRef.
What is the Difference Between Actor Reference and Path?
An actor reference designates a single actor and the life-cycle of the reference matches that actor’s life-cycle; an actor path represents a name which may or may not be inhabited by an actor and the path itself does not have a life-cycle, it never becomes invalid. You can create an actor path without creating an actor, but you cannot create an actor reference without creating corresponding actor.
You can create an actor, terminate it, and then create a new actor with the same actor path. The newly created actor is a new incarnation of the actor. It is not the same actor. An actor reference to the old incarnation is not valid for the new incarnation. Messages sent to the old actor reference will not be delivered to the new incarnation even though they have the same path.

How to get a reference to an existing actor from a non-actor in Akka?

In my application, I have a class which needs to communicate with an existing actor already created in an actorSystem. How do I get a reference to that actor from this non-actor class?
If you have the reference to the actor system (https://doc.akka.io/api/akka/current/akka/actor/ActorSystem.html), then you can simply invoke actorSelection with the path of the actor. This will give you an ActorSelection, on which you can call resolveOne, and then wait until you get the reference of the actor. Once you have the actor reference, you can send messages to it.
Here is more information about addressing actors: https://doc.akka.io/docs/akka/current/general/addressing.html .

Akka Send Delayed Message to self cannot Find implicit ExecutionContext

I am using Akka 2.1.4. I need one of my actors to send a delayed message to itself.
I have tried, from within the Actor's receive:
context.system.scheduler.scheduleOnce(1 second, self, msg)
However, it does not compile, since it cannot find the implicit ExecutionContext. Where can I get it from?.
NOTE: I am aware that the actual sender will not be my actor, but that is OK, since I don't need to know who the sender is.
You could also do it like this:
class MyActor extends Actor{
import context._
...
}
This way you are assured that you are getting the dispatcher assigned to that actor in case it differs from the main dispatcher for the system (which is what you are getting with your solution).
I think I have found it:
import myActorSystem.dispatcher
context.system.scheduler.scheduleOnce(1 second, self, msg)
Now it compiles.

Getting instance of class used to create an actor in Akka in test

How do I get instance of class I passed to Props when creating an actor with ActorSystem.actorOf? I need that for unit tests to get reference to some properties of the actor, so the actor is local in the same JVM as test.
I don't want to use Akka's test framework because I need the actor live, it's kind of integration tests.
The underlying instance of an Actor subclass is well and truly sealed off from you and you're not going to get at it without mucking with Akka code itself. If you look at the definition of the ActorRef you'll see that it doesn't even contain a reference to the Actor!
Similarly, you cannot instantiate Actor subclasses directly using new.
I guess the Akka designers were serious about the ActorRef / Actor firewall...
The Akka Testkit is made for integration testing. To get access to the internal state of an actor send it a message asking for it. Your actor can reply to the sender which is the TestKit's testActor.

How do I create a child Akka2 actor when all I have is an ActorRef to the parent?

In need to create an Akka2 actor (derived from UntypedActor) as a child of an existing actor (also derived from UntypedActor). The only reference I have to the parent actor is an ActorRef. Is there any way to do this? I'd like to call the parent's UntypedActorContext.actorOf() method, but don't know how to get a reference to it using the Akka API. Is there a better way of accomplishing my goal?
You cannot force someone to conceive against their will. Your actor needs to receive a message to which it responds by creating a new actor and send you the ref to that actor.
Can you change the code of the parent actor? You could for example add a handler for a message of type Props in your parent and create the child there. It is not possible to get the context outside of the actor class.