Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Exercises

Exercise 1: Hello Actor

Task: Create an actor named HelloActor that receives a String message and prints out Hello, [message]!.

import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.Behavior

object HelloActor {
  final case class SayHello(name: String)

  def apply(): Behavior[SayHello] = Behaviors.receive { (context, message) =>
    println(s"Hello, ${message.name}!")
    Behaviors.same
  }
}

// App to test HelloActor
object HelloApp extends App {
  val system: ActorSystem[HelloActor.SayHello] = ActorSystem(HelloActor(), "helloSystem")

  system ! HelloActor.SayHello("Akka")
}

Exercise 2: Counter Actor

Task: Implement a CounterActor that can receive messages to increment, decrement, and print its internal count.

object CounterActor {
  sealed trait Command
  case object Increment extends Command
  case object Decrement extends Command
  case object Print extends Command

  def apply(): Behavior[Command] = counterBehavior(0)

  private def counterBehavior(count: Int): Behavior[Command] =
    Behaviors.receive { (context, message) =>
      message match {
        case Increment => counterBehavior(count + 1)
        case Decrement => counterBehavior(count - 1)
        case Print =>
          println(s"Current count is $count")
          Behaviors.same
      }
    }
}

// App to test CounterActor
object CounterApp extends App {
  val system: ActorSystem[CounterActor.Command] = ActorSystem(CounterActor(), "counterSystem")

  system ! CounterActor.Increment
  system ! CounterActor.Increment
  system ! CounterActor.Decrement
  system ! CounterActor.Print // Should print "Current count is 1"
}

Exercise 3: Ping-Pong Actors

Task: Create two actors, PingActor and PongActor. PingActor should send a ping message to PongActor, and PongActor should respond with a pong message.

object PingPongActor {
  sealed trait Command
  case class Ping(replyTo: ActorRef[Command]) extends Command
  case class Pong(replyTo: ActorRef[Command]) extends Command

  def apply(): Behavior[Command] = Behaviors.receive { (context, message) =>
    message match {
      case Ping(replyTo) =>
        println("Ping received")
        replyTo ! Pong(context.self)
        Behaviors.same
      case Pong(replyTo) =>
        println("Pong received")
        replyTo ! Ping(context.self)
        Behaviors.same
    }
  }
}

// App to test PingPongActor
object PingPongApp extends App {
  val system: ActorSystem[PingPongActor.Command] = ActorSystem(PingPongActor(), "pingPongSystem")
  
  val pongActor = system
  val pingActor = system

  pingActor ! PingPongActor.Ping(pongActor)
}