Akka Scheduler throws exceptions only in MicroKernel but works fine in eclipse IDE for scala

StackOverflow https://stackoverflow.com/questions/17890223

  •  04-06-2022
  •  | 
  •  

Question

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)
Was it helpful?

Solution

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.

OTHER TIPS

The problem my code had was that it was trying to create the ActorSystem.

and import system.dispatcher is why the code failed.

Instead the line import scala.concurrent.ExecutionContext.Implicits.global gives the default executionContext to use.

Thanks Alex for guiding in me in the right direction.

case object StartSched

class Scheduler extends Actor with ActorLogging {
    import transactions._
    log.info("Scheduler initializing.")
    self!StartSched
    def receive = {
    case StartSched =>{
    import scala.concurrent.ExecutionContext.Implicits.global
    context.system.scheduler.schedule( 30 milliseconds, (1000*60*30) milliseconds){
        self ! updateUows(new Timestamp(new java.util.Date().getTime()))
      }
    }
    case updateUows(time) => { 
        log.info("updateuow to be sent.")
        context.parent!updateUows(time) 
    }
    case _=>{log.info("Don't know why we reached here.")}

}
}

Roland's answer in the comments is the correct one. java.lang.NoSuchMethodError in Scala usually means that you use binary incompatible libraries.

You either use different major Scala versions in your IDE project and in your Microkernel app, or different major Akka versions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top