Let’s dive into the Akka Actor Lifecycle

Knoldus Blog Audio
Reading Time: 4 minutes

In this post we’ll see the Akka Actor Lifecycle. But before that, let us understand what are akka actors.

Akka Actor

An actor is an object that receives messages and takes actions to handle them. It is decoupled from the source of the message and its only responsibility is to properly recognise the type of message it has received and take action accordingly.

Akka Actor Lifecycle

The lifecycle of an actor begins when the actorOf( ) method is called either by the system or by the context. Actors can be started, restarted, and stopped. Akka provides life cycle methods for Actor, which we can override and provide specific implementation accordingly.

For example, before an actor starts, we could attempt to connect to a database. We could also release resources that the actor used when we know the actor is about to be stopped. We could also restore an actor to its previous state in the case exception.

Akka Actor life cycle methods

preStart()

You can override preStart() method to provide a specific implementation for an Actor. You can control what the actor should do just before it starts. It is invoked during the initialization of the first instance of the actor. This is the place where you’d acquire any resources you might need like database connections, files, etc. Let’s take an example


import akka.actor.{Actor, ActorSystem, Props}

class PreStart extends Actor{
  override def receive: Receive ={
    case name => println("Hello " + name)
  }

  override def preStart(): Unit = {
    println("preStart() method called...")
  }
}

object Application extends App{
  val system = ActorSystem("ActorLifeCycleDemo")
  val actor = system.actorOf(Props[PreStart], "actor")
  actor ! "knoldus"
}

In the above example you can see, we have override the preStart() method. When we create the instance of the actor it get invoked.

postStop()

You can override postStart() method as well to provide a specific implementation for an Actor. You can control what the actor should do when it’s about to be stopped. Once this method is called, the actor will stop receiving any new messages and the current messages will be redirected to the dead letter mailbox. This method is used to release resources after stopping the Actor. Let’s take an example

import akka.actor.{Actor, ActorSystem, Props}


class PostStop extends Actor{
  override def receive: Receive ={
    case name => println("Hello " + name)
  }

  override def postStop(): Unit = {
    println("postStop() method called...")
  }
}

object Application extends App{
  val system = ActorSystem("ActorLifeCycleDemo")
  val actor = system.actorOf(Props[PostStop], "actor")
  actor ! "knoldus"
  system.stop(actor)
}

In the above example you can see, we have override the postStop() method. When the actor got stopped, this method is invoked.

preRestart()

You can override preRestart() method as well to provide a specific implementation for an Actor when an actor is about to restart due to some exception. This method helps us to handle what happens in case an actor fails and is restarting for some reason. Let’s take an example

import akka.actor.{Actor, ActorSystem, Props}


class PreRestart extends Actor{
  override def receive: Receive ={
    case number:Int => number/0
    case name => println("Hello " + name)
  }

  override def preRestart(reason:Throwable, message: Option[Any]): Unit = {
    println("preRestart() method called...")
    println("Reason : " + reason)
  }
}

object Application extends App{
  val system = ActorSystem("ActorLifeCycleDemo")
  val actor = system.actorOf(Props[PreRestart], "actor")
  actor ! 20
}

In the above example you can see, we have override the preRestart() method. When the actor is about to restart due to ArithmeticException, this method is invoked.

postRestart()

You can override postRestart() method as well to provide a specific implementation for an Actor when an actor has restarted due to some the exception. It is used to allow reinitialization after an Actor crash due to exception. Let’s take an example

package org.knoldus.bootstrap

import akka.actor.{Actor, ActorSystem, Props}


class PostRestart extends Actor{
  override def receive: Receive ={
    case number:Int => number/0
    case name => println("Hello " + name)
  }

  override def postRestart(reason:Throwable): Unit = {
    println("postRestart() method called...")
    println("Reason : " + reason)
  }
}

object Application extends App{
  val system = ActorSystem("ActorLifeCycleDemo")
  val actor = system.actorOf(Props[PostRestart], "actor")
  actor ! 20
}

What happens when an actor restart

  • It invoked its preRestart() method.
  • To replace the failed actor we need a new actor. The actorOf( ) method is then called to produce a new instance.
  • Then, the new instance’s postRestart( ) is invoked.

References

If you find this article interesting, please check out our other articles.

Written by 

Asbin Bhadra is a Software consultant at Knoldus Inc. Knoldus does niche Reactive and Big Data product development on Scala, Spark, and Functional Java. He is recognized as a good team player, a dedicated and responsible professional, and a technology enthusiast. His current passions include utilizing the power of Scala, Akka, and Play to make Reactive systems. He has also contributed to various Akka, Play, and Scala-based templates.

Leave a Reply