Introduction to Akka Typed with Scala for beginners.
Tags: Akka Http, Scala, Akka, Play Framework, Akka Streams

Before we start implementing the project i would like to suggest few best practices if you are new to Scala or already into Scala but were always confused on how to initialize the API.

traits and case classes

traits are like skeletons to extend/creating small groups of constants by adding them as mixins

if any class/case class is extended by trait then it has to use all the methods/functions defined in the trait except if the methods/functions are Pre-defined they will be auto imported(You can override the methods/functions if you want which is a whole different topic “Abstract Classes”) enumerations is all you do before we start implementing the logic into the project Case-classes are good for modeling immutable data a case class has all of the functionality of a regular class, and more. When the compiler sees the case keyword in front of a class, it generates code for you, with the following benefits:

Case class constructor parameters are public Val fields by default, so accessor methods are generated for each parameter.

an apply method is created in the companion object of the class, so you don’t need to use the new keyword to create a new instance of the class.

an unapply method is generated, which lets you use case classes in more ways in match expressions.

a copy method is generated in the class. You may not use this feature in Scala/OOP code, but it’s used all the time in Scala/FP.

equals and hashcode methods are generated, which let you compare objects and easily use them as keys in maps.

a default toString method is generated, which is helpful for debugging.

Required Imports

import akka.actor.typed.scaladsl.Behaviors

import akka.actor.typed.{ActorRef, ActorSystem, Behavior}

import scala.concurrent.ExecutionContextExecutor

Actor API/Protocol

declare traits and case classes as a part of enumerations

sealed trait — A sealed trait can be extended only in the same file as its declaration.

sealed trait MeanPool

case class comments(what:String) extends MeanPool

Define the Behavior in the main app-

object DeadPoolActor extends App{

def apply(): Behavior[MeanPool] = {

Behaviors.receive {

case (context, comments(comment)) =>

context.log.info(comment)

Behaviors.same

}

}

You can create behavior by declaring Behaviors._ factory with apply method.

“apply is a function that applies a function to arguments”.

Behaviors come with different message handling structure which replaces _ with below examples.

The behavior of an actor defines how it reacts to the messages that it receives.

behavior always returns behavior,

1- Behaviors.receive = receives (context, message) or with only 1 argument when context is already accessible by other means.

2- Behaviors.receiveMessage = receives only message.

3- Behaviors.receivePartial = actor `Behavior` from a partial message handler which treats undefined messages as unhandled.

4-Behaviors.setup = `setup` is a factory for a behavior. Creation of the behavior instance is deferred until the actor is started, as opposed to [[Behaviors.receive]] that creates the behavior instance immediately before the actor is running. `setup` is typically used as the outer most behavior when spawning an actor, but it can also be returned as the next behavior when processing a message or signal.

and many other per-defined methods, that's the beauty of Akka toolkit it comes with all the predefined models and supporting types.

use pattern matching to handle different types of messages and exceptions.

Pattern matching is a mechanism for checking a value against a pattern. A successful match can also deconstruct a value into its constituent parts.

log messages to console to display results with the help of actor context.

Behaviors.same = Return this behavior from message processing in order to advise the system to reuse the previous behavior, including the hint that the message has not been handled.

Create ActorSystem

implicit val system: ActorSystem[MeanPool] = ActorSystem(DeadPoolActor(), "DeadPoolActor1")

ActorSystem is the main for managing actors, logging, scheduling, watching, etc.

Actor System takes guardianBehavior with type Behavior[Type] and a name

ActorSystem(guardianBehavior: Behavior[T], name: String)

always declare system as implicit , implicits are syntactic sugar of Scala.

when val are marked by the implicit keyword at the start of the parameter list. If the parameters in that parameter list are not passed as usual, Scala will look if it can get an implicit value of the correct type, and if it can, compiler will pass it automatically.

Send Messages to Actor System

val findFrancis: ActorRef[MeanPool] = system



findFrancis ! comments("Maximum Effort")

assign the system to a val so that we can pass messages to the system , in-turn system will handle the actor Behavior for the API.

Output

Output

There, our actor is returning results and dead pool is searching for Francis.

lets hope he will find him , if not he might do some nasty stuff.

Complete Code Snippet

import akka.actor.typed.{ActorRef, ActorSystem, Behavior}

import akka.actor.typed.scaladsl.Behaviors



sealed trait MeanPool

case class comments(what:String) extends MeanPool



object DeadPoolActor extends App{

def apply(): Behavior[MeanPool] = {

Behaviors.receive {

case (context, comments(comment)) =>

context.log.info(comment)

Behaviors.same

}

}

implicit val system: ActorSystem[MeanPool] = ActorSystem(DeadPoolActor(), "DeadPoolActor1")



val findFrancis: ActorRef[MeanPool] = system



findFrancis ! comments("Maximum Effort")

}

There! all caught up.

check out our page YolkOrbit for more posts,

can’t wait to simplify and explain more advanced topics for you, get back for more for articles on PlayFramework,Akka, Akka Streams, Akka HTTP with Scala.

Cheers😎🍻.