Over a million developers have joined DZone.

Getting Started With Actors: Akka in a Nutshell

Akka uses its hierarchical actor system to encapsulate state and behavior. See how actors are built from one another and how they communicate.

· Java Zone

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

Actors are objects which encapsulate state and behavior. They communicate by exchanging messages. We can consider an actor as a person.

Like a software development team, actors form hierarchies. In a team, there is a project manager who takes requirements from client and distributes it over to different team leads. Then, those team leads further distribute the tasks to other team members. Team members, after finishing their tasks, report to their team lead about the status.

Similarly, an actor might want to split up a task into smaller tasks. For that, the actor creates child actors, and if by any means the child actor is unable to execute successfully, then it will send a corresponding failure message to its parent.

Actor System

An actor system manages the resources it is configured to use in order to run the actors it contains.

The actor system, as a collaborating ensemble of actors, is the natural unit for managing shared facilities, like scheduling services, configuration, logging, etc.

Components of the Actor System

  • User guardian actor: The user guardian actor is the parent of all actors we create.
  • System guardian actor: The system guardian actor is the parent of all actors Akka itself creates.
  • Dead Letter Office: The dead letter office is an actor just like other actors, but it's a bit of a special case. Every time a message is sent to an actor that does not exist or is already running, it instead goes to the Dead Letter Office.
  • Scheduler: As you might have guessed, the scheduler is used for scheduling tasks.

Creating an Actor With Props

Props is a configuration class to specify options for the creation of actors. Here are some examples of how to create a Props instance:

val props1 = Props[MyActor]
val props2 = Props(new ActorWithArgs(“args”))
val prop3 = Props(classOf[ActorWithArgs], “arg”)


Note: The recommended approach to create the Props actor is not supported for cases when the actor constructor takes value classes as arguments.

Declaring one actor within another is very dangerous and breaks actor encapsulation. Never pass an actor’s reference into Props!

The recommended practice is defining the Props method inside the companion object.

object MyActor {
    def props(num: Int): Props = Props(new MyActor(num))
}

class MyActor(num: Int) extends Actor {
    def receive = {
        case x: Int => sender() ! (x + num)
    }
}

class MyAnotherActor extends Actor {
    context.actorOf(MyActor.props(10), "my-actor")
}


Also, declaring what messages an actor can receive in its companion object is a recommended practice.

object MyActor {
    case class Greeting(from: String)
    case object Bye
}

class MyActor extends Actor {
    import MyActor._

    def receive = {
        case Greeting(greeter) => println(s”Hello $greeter”)
        case Bye => println(s”Good by everyone”)
    }
}


Tell vs. Ask

There are two ways we can talk to an actor:

  • Tell (!): Fire and forget, which means you send a message asynchronously and aren’t interested in the result.
  • Ask (?): Ask also sends the message asynchronously, but unlike Tell, it receives a result in the future.
object MyActor {
    case class Sum(a: Int, b: Int)
}

class MyActor extends Actor {
    override def receive: Receive = {
        case Sum(a: Int, b: Int) => sender() ! (a + b)
        case _ => sender() ! 0
    }
}

object TellAndAsk extends App {
    implicit val duration: Timeout = 20 seconds
    val system = ActorSystem("ask-and-tell")
    val myActor = system.actorOf(Props[MyActor], "my-actor")
    val sum: Future[Int] = (myActor ? Sum(3,4)).asInstanceOf[Future[Int]]

    println("Sum of 3 and 4 is " + Await.result(sum, Duration.Inf))
    system.terminate()
}


ActorRef vs. ActorSelection vs. ActorPath

ActorRef, ActorSelection, and ActorPath are all important parts of the Akka actor system. Let's cover them and their uses one by one.

ActorRef

ActorRef is the interface for the actor system and a reference for a single actor. When an actor stops actorRef, it starts pointing to the Dead Letter Office. That means that if any message is sent through that actor reference, it will go to the Dead Letter Office instead. Each time we create a new actor, Akka will create a new actor reference. We can create an actor reference using the actorOf method.

val system = ActorSystem(“my-actor-system”)

/*Here the actor is an actor reference*/

val actor = system.actorOf(Prop[MyActor])


ActorPath

Actors are created in a strictly hierarchical fashion. Every actor in an actor system is given a unique name. As mentioned earlier, every actor created has a parent — either a user guardian or another user-created actor. So, the path for any actor is like a file system. It starts with the root (/), then the user, then the actor. Let’s say we created an actor with the name my-actor. Its path for will be: /user/my-actor.

Similarly, if we create any actor from my-actor, then the path will look like this: /user/my-actor/ (note the root at the end — "/").

ActorSelection

ActorSelection is another way to represent an actor. Just like actorRef, we can send messages via ActorSelection. The difference is that it is created from the actor path.

system.actorSelection("/user/parent/child")


What also makes ActorSelection unique is that it stays valid even after an actor dies.

Check out the source code for ActorSelection demonstrating just that.

So that’s it for now! If you're interesting in reading more, check out our already covered topics

In our further blog series, we’ll cover the following topics:

  • Akka Persistence
  • Exploring Akka Networking
  • How to test an Actor?
  • A dive into Akka Streams

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java ,akka actors ,scala ,actor hierarchy ,tutorial

Published at DZone with permission of Prabhat Kashyap, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}