【问题标题】:Akka Scheduler throws exceptions only in MicroKernel but works fine in eclipse IDE for scalaAkka Scheduler 仅在 MicroKernel 中引发异常,但在 eclipse IDE for scala 中工作正常
【发布时间】:2013-07-29 16:49:39
【问题描述】:

我有一个如下所示的调度程序。它意味着每 30 分钟向 Actor 系统中的另一个 Actor 发送一条消息。当我在 eclipse IDE for scala 中运行此代码时,它运行良好。 但是,当我在 MicroKernel 中抛出此代码(使用可引导代码以便 Microkernel 可以调用它)时,我收到一个异常提示

java.lang.NoSuchMethodError: akka.actor.ActorSystem.dispatcher()Lscala/concurrent/ExecutionContext; 完整的堆栈跟踪如下所示。 我怀疑问题可能与在此上下文中无效的“import system.dispatcher”行有关。或者调度程序试图过早地触发消息。

请帮忙...

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) 
    }
    }

}

完整的堆栈跟踪:

    [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)

【问题讨论】:

  • 在 Eclipse 中运行良好是什么意思?你在哪里有内核?
  • 您的 IDE 和微内核下运行的类路径是否相同?似乎您的微内核应用程序可能会选择不同版本的 akka。
  • 实际上你的问题是你在使用 Akka 2.2 编译的同时尝试使用 Akka 2.1 微内核运行(两者不兼容二进制)。

标签: scala akka microkernel


【解决方案1】:

它应该使用 ActorSystem 创建 Actor,如下面的代码所示:

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])
  }
}

要在 MicroKernel 中启动它,您应该扩展 Bootable 特征并重载两个方法:startup 和 shutdown。 Docs

在 Actor 中创建 ActorSystem 是一个非常糟糕的决定。

【讨论】:

  • 如果没有行 import system.dispatcher 行 context.system.scheduler.schedule 会产生编译时错误。
  • 非常感谢您的回复亚历克斯。如果没有“import system.dispatcher”行,context.system.scheduler.schedule 行会产生编译时错误。错误是找不到隐式 ExecutionContext。我忘了提到在 Eclipse 中运行时,我将应用程序作为扩展 App 的对象运行。我的是一个 Maven 构建,我将其转换为在 Eclipse 中运行。我关注了调度程序的doc.akka.io/docs/akka/snapshot/scala/scheduler.html 链接,该链接看起来与您的建议相似。当我键入 ActorSystem("Daemon") 时,我是在重新创建或获取相同的演员系统吗? Scala 新手:)
  • And creating ActorSystem inside an Actor is a very bad decision. -- 为什么?
  • @user2624105 添加import scala.concurrent.ExecutionContext.Implicits.global。不,写ActorSystem("Daemon") 你将创建一个全新的系统
【解决方案2】:

我的代码遇到的问题是它试图创建 ActorSystem。

并且 import system.dispatcher 是代码失败的原因。

而不是 import scala.concurrent.ExecutionContext.Implicits.global 行给出了要使用的默认 executionContext。

感谢 Alex 引导我朝着正确的方向前进。

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.")}

}
}

【讨论】:

    【解决方案3】:

    罗兰在 cmets 中的答案是正确的。 Scala 中的 java.lang.NoSuchMethodError 通常意味着您使用了二进制不兼容的库。

    您可以在 IDE 项目和微内核应用程序中使用不同的主要 Scala 版本,或者使用不同的主要 Akka 版本。

    【讨论】:

      猜你喜欢
      • 2021-11-13
      • 1970-01-01
      • 2014-09-20
      • 2019-02-03
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 2018-02-11
      • 1970-01-01
      相关资源
      最近更新 更多