I have a scheduler that looks like given below. It is meant to send a message every 30 minute to another actor in the Actor system. This code works fine when I run it in eclipse IDE for scala. However when I throw this code(with the bootable so that Microkernel can invoke it) in MicroKernel, I get an exception saying
java.lang.NoSuchMethodError: akka.actor.ActorSystem.dispatcher()Lscala/concurrent/ExecutionContext; The full stack trace is given below. I suspect the problem might be related to "import system.dispatcher" line that is not valid in this context. Or the Scheduler is trying to fire the message too soon.
Please help...
scheduler.scala:
import akka.actor.Actor
import akka.actor.Props
import scala.concurrent.duration._
import akka.actor._
import java.sql.Timestamp;
import java.util.Date;
class Scheduler extends Actor with ActorLogging {
import transactions._
val system = ActorSystem("Daemon")
import system.dispatcher
log.info("Scheduler initializing.")
system.scheduler.schedule( 30 milliseconds, (1000*60*30 ) milliseconds){
self! updateUows(new Timestamp(new java.util.Date().getTime()))}
def receive = {
case updateUows(time) => {
log.info("updateuow to be sent.")
context.parent!updateUows(time)
}
}
}
The full stacktrace:
[DEBUG] [07/26/2013 15:38:23.324] [Daemon-akka.actor.default-dispatcher-4] [EventStream(akka://Daemon)] Default Loggers started
Uncaught error from thread [Daemon-akka.actor.default-dispatcher-4] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[Daemon[ERROR] [07/26/2013
15:38:23.960] [Daemon-akka.actor.default-dispatcher-4] [ActorSystem(Daemon)] Uncaught error from thread [Daemon-akka.actor.default-dispatcher-4] shutting down JVM since 'akka
.jvm-exit-on-fatal-error' is enabled
java.lang.NoSuchMethodError: akka.actor.ActorSystem.dispatcher()Lscala/concurrent/ExecutionContext;
at org.exactearth.PVDaemon.Scheduler$$anonfun$receive$1.applyOrElse(Scheduler.scala:25)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
at akka.actor.ActorCell.invoke(ActorCell.scala:386)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
at akka.dispatch.Mailbox.run(Mailbox.scala:212)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:506)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
]
java.lang.NoSuchMethodError: akka.actor.ActorSystem.dispatcher()Lscala/concurrent/ExecutionContext;
at org.exactearth.PVDaemon.Scheduler$$anonfun$receive$1.applyOrElse(Scheduler.scala:25)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
at akka.actor.ActorCell.invoke(ActorCell.scala:386)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
at akka.dispatch.Mailbox.run(Mailbox.scala:212)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:506)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Shutting down Akka...
Shutting down .............(my program)
It should create Actors with ActorSystem like in the code below:
case object StartSched
class Test extends Actor with ActorLogging {
def receive = {
case StartSched =>
context.system.scheduler.schedule( 30 milliseconds, (1000*60*30) milliseconds){
self ! updateUows(new Timestamp(new java.util.Date().getTime()))
}
}
}
object Main {
def main(args: Array[String]) {
val sys = ActorSystem("Test")
sys.actorOf(Props[Test])
}
}
To start it in MicroKernel you should extend Bootable
trait and overload two methods: startup
and shutdown
. Docs
And creating ActorSystem inside an Actor is a very bad decision.