user2066049
user2066049

Reputation: 1371

How to get actorRef without context in its companion object

If I have following Actor (MyActor) with a companion object.

object MyActor {
}
class MyActor extends Actor{
}

Now I want to delcare a method in a companion object like following

object MyActor{

def doStuff(id:String){
 (myActor ? Message1(id)).map {

}
}

where doStuff method will be called by a caller which has no knowledge of actors etc. now doStuff needs "myActor" reference in there. since object MyActor has no actor context or anything what's the way to access "myActor" actor in there?

EDIT Initialization of MyActor happens upon application startup, by a totally different Global Object, as follow.

val system = ActorSystem("MyActorSystem")
//create all first level actors here
system.actorOf(Props[MyActor], "MyActor")

Upvotes: 0

Views: 1590

Answers (3)

cmbaxter
cmbaxter

Reputation: 35463

If you really want to create your myActor elsewhere and then be able to use it in this companion, then you could try something like this:

object MyActor {       

   def doStuff(id:String)(implicit sys:ActorSystem) = {
     (sys.actorSelection("/user/MyActor") ? Message1(id)).map {}
   }
}

By making the context an input (and it doesn't have to be an implicit, could be explicit too) different pieces of code pass it in/make it available in different ways. For example, in another actor, you already have the actor system available via context.system but if you are outside of an actor, then you will probably have needed to make the actor system itself available on some sort of global object and then imported into scope.

Upvotes: 1

user908853
user908853

Reputation:

The thing is that, even though it is defined in the companion object of MyActor, doStuff can't access the reference (ActorRef) to the instantiated actor without explicitly importing the ActorRef myActor.

I think it would be better to write the MyActor object as follows:

object MyActor {
   val myActor = system.actorOf(Props[MyActor], "MyActor")

   def doStuff(id:String) = {
     (myActor ? Message1(id)).map {}
   }
}

Import this object in your Global object so that the creation of myActor would be done as soon as the Global object is used.

Upvotes: 0

AmigoNico
AmigoNico

Reputation: 6862

It sounds like you want to treat the fact that you are using an actor as an implementation detail of whatever service the companion object exposes, but you want to centralize the creation of actors (presumably to give them a supervisor). One option would be for the companion object to look up the actor.

Another would be to have the creation of the actor hidden in the companion object. The global object that creates the actors could, rather than creating MyActor directly, call an init method on the companion object with an ActorSystem argument; MyObject could save the ActorRef for later use. You'd have to make the variable @volatile in that case.

Upvotes: 1

Related Questions