How can I make an actor class to observable in scala - scala

I've tried to make my actor class observable (extends Actor with Observable[T]). However, there is an error message that I have to implement the asJavaObserver value but there is no asJavaObserver in observable trait.

Aren't you mixing two separate programming paradigms? Actors only communicate by messages. So if anyone is interested in the state change of an actor it must receive a message from the actor.
The observable stuff is for other OO programs which don't use Actor model.

Related

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 .

How to get an ActorRef from "this"

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

Is it safe to override `receive` in an Akka FSM?

I created an FSM with Akka. However, my FSM doesn't only get messages passed that are relevant for its FSM state. Its children may also pass ActorRefs up to it, which my FSM should then pass further up to its parent. Since FSMs in Akka are (naturally) also actors, I would like to override receive to catch those ActorRefs. However, doing that broke the FSM functionality of the actor. What's the proper way to handle a situation like this?
Messages that are not relevant for any FSM state can be handled in whenUnhandled:
whenUnhandled {
case Event(someActorRef: ActorRef, _) =>
context.parent ! someActorRef
stay()
}
Though, overriding receive should, afaik, work, too.

Declaring Actor state variables as mutable ones

I am fairly new with Akka framework and Concurrency concepts. And from Akka docs, I understood that only one message in the Actor mailbox would be processed at a time. So single thread would be processing Actor's state at a time. And my doubt is that, so declaring an Actor state/data variable as mutable - 'Var'(Only when 'Val' doesn't fit), will not cause inconsistent Actor states in the case of Concurrency.
I am using Scala for development. In the following Master actor, details of workers is stored in a mutable variable 'workers'. Will it be a problem with concurrency?
class Master extends PersistentActor with ActorLogging {
...
private var workers = Map[String, WorkerState]()
...
}
I think what you are doing is fine. As you said, one of the fundamental guarantees of Akka actors is that a single actor will be handling one message at a time, so there will not be inconsistent Actor states.
Akka actors conceptually each have their own light-weight thread,
which is completely shielded from the rest of the system. This means
that instead of having to synchronize access using locks you can just
write your actor code without worrying about concurrency at all.
http://doc.akka.io/docs/akka/snapshot/general/actors.html
Also, it is a good thing that you're using a var instead of a val with a mutable map :)
Another way to consider coding situations like these is to alter the actor's "state" after each message handled. Eg.:
class Master extends PersistentActor with ActorLogging {
type MyStateType = ... // eg. Map[String, WorkerState], or an immutable case class - of course, feel free to just inline the type...
def receive = handle(initState) // eg. just inline a call to Map.empty
def handle(state: MyStateType): Actor.Receive = LoggingReceive {
case MyMessageType(data) =>
... // processing data - build new state
become(handle(newState))
case ... // any other message types to be handled, etc.
}
... // rest of class implementation
}
While it is true that there is still mutable state happening here (in this case, it is the state of the actor as a whole - it becomes effectively a "non-finite state machine"), it feels better contained/hidden (to me, at least), and the "state" (or "workers") available to the actor for any given message is treated as entirely immutable.

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.