scalaakkamicrokernel

Instantiation in AKKA Microkernel


Having followed the documentation example (2.1.4), I was having trouble with a Microkernel loaded actor processing messages, where the Bootable extension class is defined as follows:

class HelloKernel extends Bootable {
  val system = ActorSystem("hellokernel")
  def startup = {
    system.actorOf(Props[HelloActor]) ! Start  
  }
  def shutdown = {
    system.shutdown()
  }
}

If a dummy (i.e. not used anywhere else in the code) instance is created, as shown below, messages are then processed as expected.

class HelloKernel extends Bootable {
  val system = ActorSystem("hellokernel")

  val dummyActor = system.actorOf(Props[HelloActor])

  def startup = {
    system.actorOf(Props[HelloActor]) ! Start  
  }
  def shutdown = {
    system.shutdown()
  }
}

Should there indeed be a dummy instantiation or, by doing it, am I causing some side effect, resulting in messages being processed?

Based on the code given by Thomas Letschert in Akka 2.1 minimal remote actor example I have turned the server side into a Microkernel hosted actor.

import akka.actor.Actor
import akka.actor.ActorLogging
import akka.actor.ActorSystem
import akka.actor.Props
import akka.kernel.Bootable


class Joe extends Actor {
  def receive = {
    case msg: String => println("joe received " + msg + " from " + sender)
    case _ => println("Received unknown msg ")
  }
}

class GreetServerKernel extends Bootable {
  val system = ActorSystem("GreetingSystem")
  val joe = system.actorOf(Props[Joe], name = "joe")
  println(joe.path)
  joe ! "local msg!"
  println("Server ready")

  def startup = {
  }

  def shutdown = {
    println("PrimeWorker: Shutting Down")
    system.shutdown
  }

}

In this case the dummy instantiation, which when removed messages are not processed, is

  val joe = system.actorOf(Props[Joe], name = "joe")

The caller code is

import akka.actor._
import akka.actor.ActorDSL._

object GreetSender extends App {
  implicit val system = ActorSystem("GreetingSystem")
  val joe = system.actorFor("akka://GreetingSystem@127.0.0.1:2554/user/joe")

  println(joe.path)

  val a = actor(new Act {
    whenStarting { joe ! "Hello Joe from remote" }
  })

  joe ! "Hello"

  println("Client has sent Hello to joe")
}

Solution

  • If the code you posted is indeed accurate, then just move the instantion of the joe instance into the startup operation instead of in the constructor for the bootable class:

    def startup = {
      system.actorOf(Props[Joe], name = "joe")
    }
    

    The actor tied to the name joe needs to have been started up before someone can look it up by name and send messages to it. It's basically the same thing as starting it up in the constructor of the bootable class, but I believe that convention dictates to do all actor instantiation in the startup function as opposed to the bootable class body (and thus the constructor)