I have the following code
lazy val restEndpoint = context.actorOf(Props[RestEndpoint], "RestEndpoint")
However, I want to dynamically load the actor if it's there for a few reasons:
Is there some 'easy' way to do this reflectively? Please don't point me at the documentation on reflection in Scala, because there is nothing easy there. If there is a Scala Reflection for Dummies discussion I would appreciate looking at that.
A working example would be greatly appreciated.
Really glad we have a Typesafe support contract. Here is the solution we came up with. I have tested the code, and it works. Note: reflection was not necessary, which made me very happy.
def actorRefForName(className: String) = try {
val actorClass = Class.forName(className)
Some(context.actorOf(Props(actorClass), actorClass.getSimpleName))
} catch {
case classNotFoundException: ClassNotFoundException =>
log.info(s"class $className not found. This actor will not be used")
None
}
. . .
lazy val kinesisProducer =
actorRefForName("com._3tierlogic.KinesisManager.producer.KinesisProducer")
. . .
def receive = {
case Start =>
kinesisProducer match {
case Some(kinesisProducerRef) =>
log.info("Starting " + kinesisProducerRef.path.name)
kinesisProducerRef ! Start
case None =>
log.info("There is no Kinesis Producer actor to start.")
}
case Started =>
// foreach is a little confusing when there is only Some or None, but
// basically we can only use our actorRef if there is one. EK
kinesisProducer.foreach { kinesisProducerRef =>
if (sender.equals(kinesisProducerRef)) {
log.info(kinesisProducerRef.path.name + " Started")
log.info("Starting " + restEndpointRef.path.name)
IO(Http)(context.system) ! Http.Bind(restEndpointRef, "0.0.0.0", port = 8061)
}
}
While this adds a little extra boilerplate, I don't think it's too bad. There are probably ways I could reduce the boilerplate more.
Typesafe also recommended I look at Akka Extensions and ExtendedActorSystem