Following the Akka tutorials https://doc.akka.io/docs/akka/current/typed/guide/tutorial_1.html I have modified sample code to send a message to an akka actor every 3 seconds:
scheduler.scheduleAtFixedRate(
initialDelay = Duration(0, TimeUnit.SECONDS),
interval = Duration(3, TimeUnit.SECONDS))(
runnable = task)
}
I'm unable to safely compiling changing the message return in Main from String to List[String]. So instead of firstRef ! "printit"
, change to firstRef ! List("printit")
but this causes compiler error:
To fix the compiler error I make changes to:
class Main(context: ActorContext[String]) extends AbstractBehavior[List[String]](context) {
override def onMessage(msg: String): Behavior[List[String]] =
def apply(): Behavior[List[String]] =
where previously this contained:
class Main(context: ActorContext[String]) extends AbstractBehavior[String](context) {
override def onMessage(msg: String): Behavior[String] =
def apply(): Behavior[String] =
What needs to change in order to return List[String]
instead of String
in the Main
actor ?
complete code (without changes):
import java.util.concurrent.TimeUnit
import akka.actor.typed.ActorSystem
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.AbstractBehavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import map.QTableRow
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
import scala.collection.mutable.ListBuffer
object PrintMyActorRefActor {
def apply(): Behavior[String] =
Behaviors.setup(context => new PrintMyActorRefActor(context))
}
class PrintMyActorRefActor(context: ActorContext[String]) extends AbstractBehavior[String](context) {
override def onMessage(msg: String): Behavior[String] =
msg match {
case "printit" =>
val secondRef = context.spawn(Behaviors.empty[String], "second-actor")
println(s"Second: $secondRef")
this
}
}
object Main {
def apply(): Behavior[String] =
Behaviors.setup(context => new Main(context))
}
class Main(context: ActorContext[String]) extends AbstractBehavior[String](context) {
override def onMessage(msg: String): Behavior[String] =
msg match {
case "getdata" =>
val firstRef = context.spawn(PrintMyActorRefActor(), "first-actor"+String.valueOf(System.currentTimeMillis()))
println(s"First: $firstRef")
firstRef ! "printit"
this
}
}
object ActorHierarchyExperiments extends App {
val testSystem = ActorSystem(Main(), "testSystem")
val scheduler = testSystem.scheduler
val task = new Runnable { def run() {
testSystem ! "getdata" }
}
scheduler.scheduleAtFixedRate(
initialDelay = Duration(0, TimeUnit.SECONDS),
interval = Duration(3, TimeUnit.SECONDS))(
runnable = task)
}
The firstRef
actor reference references an instance of PrintMyActorRefActor
, which is a Behavior[ String ]
, so to send any List[ String ]
to the ref, the PrintMyActorRefActor
needs to be able to recieve it. Changing this, including the signature of its recieve
message, should make the snippet compile. Now, of course, you'll need to change the behaviour of the PrintMyActorRefActor.onMessage( msg: List[ String ] ): Behavior[ List[ String ] ]
to deal with the list instead of the single string...
Complete transformed code snippet:
import java.util.concurrent.TimeUnit
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}
import akka.actor.typed.{ActorSystem, Behavior}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object PrintMyActorRefActor {
def apply(): Behavior[List[String]] =
Behaviors.setup(context => new PrintMyActorRefActor(context))
}
class PrintMyActorRefActor(context: ActorContext[List[String]]) extends AbstractBehavior[List[String]](context) {
override def onMessage(msg: List[String]): Behavior[List[String]] =
msg match {
case "printit" :: xs => // ignores all but the head element
val secondRef = context.spawn(Behaviors.empty[String], "second-actor")
println(s"Second: $secondRef")
this
}
}
object Main {
def apply(): Behavior[String] =
Behaviors.setup(context => new Main(context))
}
class Main(context: ActorContext[String]) extends AbstractBehavior[String](context) {
override def onMessage(msg: String): Behavior[String] =
msg match {
case "getdata" =>
val firstRef = context.spawn(PrintMyActorRefActor(), "first-actor" + String.valueOf(System.currentTimeMillis()))
println(s"First: $firstRef")
firstRef ! List("printit")
this
}
}
object ActorHierarchyExperiments extends App {
val testSystem = ActorSystem(Main(), "testSystem")
val scheduler = testSystem.scheduler
val task = new Runnable {
def run() {
testSystem ! "getdata"
}
}
scheduler.scheduleAtFixedRate(
initialDelay = Duration(0, TimeUnit.SECONDS),
interval = Duration(3, TimeUnit.SECONDS))(
runnable = task)
}