Todo App
Creating a simple Todo app using Akka's untyped actors can be an excellent way to demonstrate how to manage state, handle concurrency, and build a basic application using Akka's actor model. Below, I will walk you through the process of building a Todo app with the following functionalities:
- Add a new Todo item.
- Remove a Todo item.
- Mark a Todo item as completed.
- List all Todo items.
1. Setting Up the Project
Start by setting up your Scala project with the necessary Akka dependencies in your build.sbt:
libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.6.x"
2. Defining the Messages
First, define the messages that actors will use to communicate. Messages are immutable case classes:
// Messages
case class AddTodo(id: Int, task: String)
case class RemoveTodo(id: Int)
case class CompleteTodo(id: Int)
case object GetTodos
3. Creating the Todo Actor
The TodoActor will manage the list of Todo items. It will handle messages to add, remove, complete, and retrieve Todo items:
import akka.actor.{Actor, ActorSystem, Props}
// Todo Item case class
case class TodoItem(id: Int, task: String, completed: Boolean = false)
class TodoActor extends Actor {
var todos: Map[Int, TodoItem] = Map()
def receive: Receive = {
case AddTodo(id, task) =>
todos += id -> TodoItem(id, task)
println(s"Added Todo: $task")
case RemoveTodo(id) =>
todos.get(id) match {
case Some(todo) =>
todos -= id
println(s"Removed Todo: ${todo.task}")
case None =>
println(s"Todo with id $id not found.")
}
case CompleteTodo(id) =>
todos.get(id) match {
case Some(todo) =>
todos += id -> todo.copy(completed = true)
println(s"Completed Todo: ${todo.task}")
case None =>
println(s"Todo with id $id not found.")
}
case GetTodos =>
if (todos.isEmpty) {
println("No Todos available.")
} else {
todos.values.foreach { todo =>
val status = if (todo.completed) "Completed" else "Pending"
println(s"${todo.id}: ${todo.task} [$status]")
}
}
}
}
4. Creating the Main Application
Now, let's create a main application that will instantiate the ActorSystem, create the TodoActor, and interact with it:
object TodoApp extends App {
// Create Actor System
val system = ActorSystem("TodoSystem")
// Create TodoActor
val todoActor = system.actorOf(Props[TodoActor], "todoActor")
// Interacting with the TodoActor
todoActor ! AddTodo(1, "Buy milk")
todoActor ! AddTodo(2, "Go to the gym")
todoActor ! GetTodos
todoActor ! CompleteTodo(1)
todoActor ! GetTodos
todoActor ! RemoveTodo(2)
todoActor ! GetTodos
// Shutdown the Actor System
system.terminate()
}
5. Running the Application
To run the application, simply execute the TodoApp object in your Scala environment. The output will be:
Added Todo: Buy milk
Added Todo: Go to the gym
1: Buy milk [Pending]
2: Go to the gym [Pending]
Completed Todo: Buy milk
1: Buy milk [Completed]
2: Go to the gym [Pending]
Removed Todo: Go to the gym
1: Buy milk [Completed]
No Todos available.