Understanding the methods in the Scala/Akka Actor lifecycle

This is an excerpt from the Scala Cookbook. This is Recipe 13.4, “Understanding the methods in the Scala/Akka Actor lifecycle.”

Problem

You’re creating more complicated Akka actors, and need to understand when the lifecycle methods on an Actor are called.

Solution

In addition to its constructor, an Actor has the following life-cycle methods:

  • receive
  • preStart
  • postStop
  • preRestart
  • postRestart

To demonstrate when these methods are called, basic implementations of these methods have been created in the Kenny actor of the following example:

import akka.actor._

class Kenny extends Actor {
    println("entered the Kenny constructor")
    override def preStart { println("kenny: preStart") }
    override def postStop { println("kenny: postStop") }
    override def preRestart(reason: Throwable, message: Option[Any]) {
        println("kenny: preRestart")
        println(s" MESSAGE: ${message.getOrElse("")}")
        println(s" REASON: ${reason.getMessage}")
        super.preRestart(reason, message)
    }
    override def postRestart(reason: Throwable) {
        println("kenny: postRestart")
        println(s" REASON: ${reason.getMessage}")
        super.postRestart(reason)
    }
    def receive = {
        case ForceRestart => throw new Exception("Boom!")
        case _ => println("Kenny received a message")
    }
}

case object ForceRestart

object LifecycleDemo extends App {
    val system = ActorSystem("LifecycleDemo")
    val kenny = system.actorOf(Props[Kenny], name = "Kenny")

    println("sending kenny a simple String message")
    kenny ! "hello"
    Thread.sleep(1000)

    println("make kenny restart")
    kenny ! ForceRestart
    Thread.sleep(1000)

    println("stopping kenny")
    system.stop(kenny)

    println("shutting down system")
    system.shutdown
}

The output from this program shows when the life-cycle methods are invoked:

[info] Running LifecycleDemo
sending kenny a simple String message
entered the Kenny constructor
kenny: preStart
Kenny received a message
make kenny restart
[ERROR] [05/14/2013 10:21:54.953] [LifecycleDemo-akka.actor.default-dispatcher-4]
[akka://LifecycleDemo/user/Kenny] Boom!
java.lang.Exception: Boom!
    at Kenny$$anonfun$receive$1.applyOrElse(Test.scala:19)
    (many more lines of exception output ...)
kenny: preRestart
    MESSAGE: ForceRestart
    REASON: Boom!
kenny: postStop
entered the Kenny constructor
kenny: postRestart
    REASON: Boom!
kenny: preStart
stopping kenny
shutting down system
kenny: postStop
[success]

Discussion

As shown in the println statement at the beginning of the Kenny actor, the body of an Akka Actor is a part of the constructor, just like any regular Scala class. Along with an actor’s constructor, the pre* and post* methods can be used to initialize and close resources that your actor requires.

Notice that preRestart and postRestart call the super versions of their methods. This is because the default implementation of postRestart calls preRestart, and I want that default behavior in this application.

Table 13-1 provides a description of each life-cycle method, including an actor’s constructor.

Table 13-1. Akka actor life-cycle methods

Method Description
The actor’s constructor An actor’s constructor is called just like any other Scala class constructor, when an instance of the class is first created.
preStart Called right after the actor is started. During restarts it’s called by the default implementation of postRestart.
postStop Called after an actor is stopped, it can be used to perform any needed cleanup work. According to the Akka documentation, this hook “is guaranteed to run after message queuing has been disabled for this actor.”
preRestart According to the Akka documentation, when an actor is restarted, the old actor is informed of the process when preRestart is called with the exception that caused the restart, and the message that triggered the exception. The message may be None if the restart was not caused by processing a message.
postRestart The postRestart method of the new actor is invoked with the exception that caused the restart. In the default implementation, the preStart method is called.

See Also