ps0604 ps0604 - 11 days ago 5
Scala Question

How to name an actor?

The data layer in my web application is comprised of Akka actors. Whenever I need to access data, I invoke the ActorSystem mechanism like so:

val myActor = system.actorOf(Props[MyActor], name = "myactor")
implicit val timeout = Timeout(120 seconds)
val future = myActor ? Request1
val result = Await.result(future, timeout.duration)


I'm using Play, and the ActorSystem variable is obtained through injection:

class MyClass @Inject() (system: ActorSystem)


But I'm getting the following exception saying that the actor name is not unique the second time I access the function, how to fix this? How to name the actor, taking into account that can be used concurrently by more than one thread?


play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution
exception[[InvalidActorNameException: actor name [myactor] is not
unique!]]


** EDIT **

What I'm trying to achieve is something similar to having a container of Entity Beans in the EJB model, where each actor would be an Entity Bean. The difference I'm noticing is that the actors are not created/destroyed automatically as needed.

Answer

Depending on your goal, the question may be not how to name an actor, but when to create it. You are creating a new actor every time you need to access some data. I suppose you aren't stopping old actors when they are no longer needed.

You should probably create an actor once (or multiple times if you want a pool of actors, but using different names) and reuse it later by keeping an ActorRef somewhere or using dependency injected actors. You can also use system.actorFor or system.actorSelection (depending on Akka version you're using) if you really need to.

Most of the time you don't even need an explicit ActorRef because you want to reply to a sender of some message.

If you have to create a separate actor each time, then see Wonpyo's answer. In my opinion, though, you could simply use a Future directly instead.

There is a great guide on Actors in the Akka documentation.

Edit:

Since you specified you want each actor to act like a DAO class, I think it should look something like:

// Somewhere in some singleton object
val personDao = system.actorOf(Props[PersonDaoActor], name = "personDao")
val fruitDao  = system.actorOf(Props[FruitDaoActor],  name = "fruitDao")

Then, when you need to access some data:

val johnSmithFuture = personDao ? Get("John Smith")
johnSmithFuture.map {
  case Person(name, age) => println(s"${name} ${age}")
}

Alternatively, instead of personDao you can use system.actorFor("personDao") (or system.actorSelection equivalent in Akka 2.4).

Using Await defeats the purpose of Akka.

Comments