我试图在我为 SBT 构建编写的任务中运行一个相当简单的 HTTP POST 请求,并且看到 SBT 似乎没有帮助程序,我决定使用喷雾客户端来完成这项任务。
在 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 文件。在查看我猜测可能与构建执行类路径(
reload plugins
然后是 show runtime:fullClasspath
在 sbt 中)相关的内容时,该 jar 出现在列表中。我也没有在谷歌上搜索任何相关的东西,无法传达问题在于从 SBT 构建中运行 akka。
最后,我真的不知道 'akka' 配置 key 是如何丢失的。任何人都可以帮忙吗?
最佳答案
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 中使用的类加载器(当它不作为参数传递时):
Thread.currentThread.getContextClassLoader
getClassLoader
在非 Akka 堆栈的类上将调用堆栈框架向上 ActorSystem.getClass.getClassLoader
所以这就是上述改变上下文类加载器的解决方案有效的原因。
至于在实践中使用的类加载器,我得到了预期的行为
val cl = getClass.getClassLoader
(来自我的构建定义类)因为该类加载器包含所有构建定义、插件和依赖项。它还有效地使上面的第 1 步表现得像第 2 步。尽管如此,我最终还是通过调用
ActorSystem("someName", ConfigFactory.load(cl), cl)
创建了 ActorSystem。并且不涉及上下文类加载器,这似乎更清晰(对于像我这样不知道上下文类加载器是什么或做什么的人来说,这不那么可怕)TL;博士 代替
val system = ActorSystem()
写
val cl = getClass.getClassLoader
val system = ActorSystem("mySystem", ConfigFactory.load(cl), cl)
关于sbt - 在 SBT 构建任务 : reference configuration unexpectedly missing 中运行 akka,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20429568/