Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

call methods on akka actors in scala

Tags:

scala

akka

actor

I have a an actor defined as so:

class nodeActor(ID: String) extends Actor

which contains a method, which is used to set up the actor before it is started:

def addRef(actor:ActorRef)

I instantiate this actor as so:

val node1 = system.actorOf(Props(new nodeActor("node1")), name="node1")

which returns me an ActorRef. The compiler doesn't let me call "addRef" on an ActorRef since it's a member of the subtype. So I cast the node using:

node1.asInstanceOf[nodeActor].addRef(link1)

Which keeps the compiler happy. Then at runtime I get

java.lang.ClassCastException: akka.actor.LocalActorRef cannot be cast to ActorStressTest.nodeActor

which doesn't even seem to make sense to me since it's a subtype and I should be able to cast to it.

Ideas?

like image 741
Alex Avatar asked Nov 08 '12 14:11

Alex


People also ask

How can I send a message to an actor in Akka?

1) Akka Actor tell() Method It works on "fire-forget" approach. You can also use ! (bang) exclamation mark to send message. This is the preferred way of sending messages.

Does Akka use threads?

Behind the scenes, Akka runs actors on real threads and many actors may share one thread. A Actor can create many actors called child actors. Actors interact only through asynchronous messages and never through direct method calls.

What is alternative to Akka?

Spring, Scala, Erlang, Kafka, and Spring Boot are the most popular alternatives and competitors to Akka.


3 Answers

If you want to do this for testing then when creating actor you can just do this:

import akka.testkit.TestActorRef
val actorRef = TestActorRef[MyActor]
val actor = actorRef.underlyingActor

Then you can run methods on actor

like image 91
goldeneye13 Avatar answered Nov 12 '22 17:11

goldeneye13


You're not supposed to call an actor's methods directly from another class. It breaks the whole design of the system, which is

  • to encapsulate the actor's specific implementation by communicating only with the ActorRef obtained with the call to actorOf or actorFor
  • to limit communication between actors to message passing, using the available (!, ?) methods

If you need to create a reference in ActorA to another ActorB you can:

  • Create the ref to ActorB in the ActorA's initialization code as shown in http://doc.akka.io/docs/akka/2.0.3/scala/actors.html
  • Send the ActorB's reference to the ActorA as a specific message. Then ActorA can store the reference within receive implementation

If you need to call a method to satisfy an Interface/Trait constraint, have a look at Typed Actors

like image 45
pagoda_5b Avatar answered Nov 12 '22 17:11

pagoda_5b


You can cast anything to anything and the compiler will happily do so, but the check at runtime will fail if it's not possible. The ActorRef is not an instance of your Actor class or a subtype of it.

When you do this:

system.actorOf(Props(new nodeActor("node1")), name="node1")

You get back an ActorRef to which you should only send messages. Apart from that, the actor is started immediately when you call system.actorOf, so trying to call a method on the Actor instance before it is started is not possible.

Here is a description of actors from the Akka Docs explaining actor references.

like image 1
Björn Antonsson Avatar answered Nov 12 '22 17:11

Björn Antonsson