How to get started with a simple Scala/Akka Actor (Hello, world)

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 13.1, “How to get started with a simple Scala/Akka Actor.”

Problem

You want to begin using Akka actors to build concurrency into your Scala applications.

Solution

Create an actor by extending the akka.actor.Actor class and writing a receive method in your class. The receive method should be implemented with a case statement that allows the actor to respond to the different messages it receives.

To demonstrate this, create an SBT project directory named HelloAkka, move into that directory, and then add the necessary Akka resolver and dependency information to your build.sbt file:

name := "Hello Test #1"

version := "1.0"

scalaVersion := "2.10.0"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.1.2"

At the time of this writing, the Akka actor library is being migrated into the Scala distribution, but it’s still necessary to include the library as a dependency in your SBT build.sbt file (or download the necessary JAR files manually). This may change in the future, in which case the dependencies shown in this chapter may not be necessary.

Next, define an actor that responds when it receives the String literal hello as a message. To do this, save the following source code to a file named Hello.scala in the root directory of your SBT project. Notice how the literal hello is used in the first case statement in the receive method of the HelloActor class:

import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.Props
class HelloActor extends Actor {
    def receive = {
        case "hello" => println("hello back at you")
        case _       => println("huh?")
    }
}

object Main extends App {

    // an actor needs an ActorSystem
    val system = ActorSystem("HelloSystem")

    // create and start the actor
    val helloActor = system.actorOf(Props[HelloActor], name = "helloactor")

    // send the actor two messages
    helloActor ! "hello"
    helloActor ! "buenos dias"

    // shut down the system
    system.shutdown

}

Then run the application like this:

$ sbt run

After SBT downloads the Akka JAR files and their dependencies, you should see the following output from the println statements in the HelloActor class:

[info] Running Main
hello back at you
huh?

Discussion

Here’s a step-by-step description of the Scala/Akka code:

  • The import statements import the members that are needed.
  • An Actor named HelloActor is defined.
  • HelloActor’s behavior is implemented by defining a receive method, which is implemented using a match expression.
  • When HelloActor receives the String literal hello as a message, it prints the first reply, and when it receives any other type of message, it prints the second reply.
  • The Main object is created to test the actor.
  • In Main, an ActorSystem is needed to get things started, so one is created. The ActorSystem takes a name as an argument, so give the system a meaningful name. The name must consist of only the [a-zA-Z0-9] characters, and zero or more hyphens, and a hyphen can’t be used in the leading space.
  • Actors can be created at the ActorSystem level, or inside other actors. At the ActorSystem level, actor instances are created with the system.actorOf method. The helloActor line shows the syntax to create an Actor with a constructor that takes no arguments.
  • Actors are automatically started (asynchronously) when they are created, so there’s no need to call any sort of “start” or “run” method.
  • Messages are sent to actors with the ! method, and Main sends two messages to the actor with the ! method: hello and buenos dias.
  • helloActor responds to the messages by executing its println statements.
  • The ActorSystem is shut down.

That’s all you need to create and use your first Akka Actor.

Details

When implementing the behavior of an Akka actor, you should define a receive method using a match expression, as shown in the example. Your method should handle all potential messages that can be sent to the actor; otherwise, an UnhandledMessage will be published to the ActorSystem’s EventStream. As a practical matter, this means having the catch-all case _ line in your match expression.

In this example, messages were sent to the HelloActor class as String literals, but other recipes will show how to send messages to actors using other types. Messages should be immutable, so for simple examples, a String works well.

ActorSystem

The API documentation describes an ActorSystem like this:

“An actor system is a hierarchical group of actors which share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. It is also the entry point for creating or looking up actors.”

An ActorSystem is the structure that allocates one or more threads for your application, so you typically create one ActorSystem per (logical) application.

As an example, I wrote a “speech interaction” application named SARAH that lets me interact with a Mac OS X computer using only voice commands. Besides allowing interactive commands, SARAH also runs background tasks to check my email, notify me of Facebook and Twitter events, stock prices, etc.

SARAH uses a plug-in architecture, so there are plug-ins for each major area of functionality (such as an email plug-in, Facebook plug-in, Twitter plug-in, etc.). A plug-in typically has one parent actor that delegates work to child actors as necessary. All of these plug-ins run under one ActorSystem.

When SARAH starts, it starts the ActorSystem using the same method shown in the Solution. Once started, it creates three main actors named brain, ears, and `mouth, and then starts its plug-ins.

As an interesting experiment with the ActorSystem, remove the system.shutdown line at the end of the Main object. You’ll see that the application doesn’t terminate, because the actors and system are still running. (Press Control-C to terminate the application.)

Akka ActorRef

When you call the actorOf method on an ActorSystem, it starts the actor asynchronously and returns an instance of an ActorRef. This reference is a “handle” to the actor, which you can think of as being a façade or broker between you and the actual actor. This façade keeps you from doing things that would break the Actor model, such as reaching into the Actor instance and attempting to directly mutate variables. Tasks like this should only be done by passing messages to the actor, and the hands-off approach of an ActorRef helps reinforce proper programming practices.

(Again, think of an actor as a person you can only communicate with by placing messages in his mailbox.)

The Akka documentation states that an ActorRef has these qualities:

  • It is immutable.
  • It has a one-to-one relationship with the Actor it represents.
  • It is serializable and network-aware. This lets you pass the ActorRef around the network.

See Also