在SBT构建任务中运行akka:意外丢失了引用配置

时间:2013-12-06 17:05:08

标签: sbt akka

我正在尝试在为我的SBT构建编写的任务中运行一个相当简单的HTTP POST请求,并且看到SBT似乎没有帮助,我决定使用spray-client来完成此任务。 / p>

project/dependencies.sbt文件中,我提出以下内容:

resolvers += "spray.io repo" at "http://repo.spray.io/"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.2.3",
  "io.spray" % "spray-client" % "1.2.0")

我的任务是通过以下方式实现的:

def uploadSite(version: String, siteArchive: File, log: Logger): HttpResponse = {

  def request: HttpRequest = Post(siteUploadUrl,
    MultipartFormData(Map(
    // abridged
    ))

  implicit val system = ActorSystem() // <-- Exception HERE!
  try {
    import system.dispatcher

    val future: Future[HttpResponse] = pipelining.sendReceive(request)

    Await.result(future, 1 minute)
  }
  finally system.shutdown()
}

当我运行以下异常时,任务失败:

com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'akka'
    at com.typesafe.config.impl.SimpleConfig.findKey(SimpleConfig.java:115)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:138)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:150)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:155)
    at com.typesafe.config.impl.SimpleConfig.getString(SimpleConfig.java:197)
    at akka.actor.ActorSystem$Settings.<init>(ActorSystem.scala:136)
    at akka.actor.ActorSystemImpl.<init>(ActorSystem.scala:470)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:111)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:93)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:82)
    at MyIO$.uploadSite(MyIO.scala:65)

我的基本分析是,reference.conf中找不到的akka-actor_2.10-2.2.3.jar文件没有被读取,因为某些原因让我感到厌烦,并且可能与SBT如何管理其类路径以运行建立。

一些精确性:我在SBT 0.13.0上(因此构建代码为Scala 2.10)并且我检查了前面提到的akka​​-actor jar确实包含一个reference.conf文件,这是预期的。在查看我 guess 可能与构建执行类路径(reload plugins然后在{s}中的show runtime:fullClasspath)相关时,该jar会出现在列表中。

我也没有通过谷歌搜索相关的任何内容,无法表达问题在于从SBT构建中的运行akka

最后,我真的不知道'akka'配置密钥是如何丢失的。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:4)

关于akka真正讨厌的事情是你需要为泛型设置更新线程本地上下文类加载器,而很多工具(比如sbt)都没有,因为他们不知道你在运行什么线程或者你需要哪个类加载器。

这是an example from the activator build:

val cl = ??? // Some mechanism of getting Akka's classpath with your classes too
val old = Thread.currentThread.getContextClassLoader
Thread.currentThread.setContextClassLoader(cl)
try doSomethingWithAkka()
finally Thread.currentThread.setContextClassLoader(old)

编辑(通过OP),以便比评论中更明显:

Akka(自2.0开始)选择它在ActorSystem中使用的类加载器(当它不作为参数传递时)通过选择第一个可用(和非空):

  1. Thread.currentThread.getContextClassLoader
  2. getClassLoader在调用堆栈上的非Akka堆栈框架类
  3. ActorSystem.getClass.getClassLoader
  4. 这就是上述变异上下文类加载器的解决方案的原因。

    对于在实践中使用的类加载器,我得到了val cl = getClass.getClassLoader(来自我的构建定义类)的预期行为,因为该类加载器包含所有构建定义,插件和依赖项。它也有效地使上面的步骤1表现得像第2步。

    最后,我通过调用ActorSystem("someName", ConfigFactory.load(cl), cl)并且没有触及上下文类加载器来创建ActorSystem,这似乎更清晰(对于像我这样不知道是什么的人来说也不那么可怕)上下文类加载器是或确实)

    TL; DR 而不是

    val system = ActorSystem()
    

    val cl = getClass.getClassLoader
    val system = ActorSystem("mySystem", ConfigFactory.load(cl), cl)