Running akka within an SBT build task: reference configuration unexpectedly missing
akka, sbt
Solution
The really annoying thing about akka is that you need to update the thread local context classloader for the generic setting, and a lot of tools (like sbt) do not, because they do not know what thread you're running on or which classloader you will need.
Here's 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)
Edit (by OP) so that this is more visible than in the comments:
Akka (since 2.0) chooses the class loader it uses in ActorSystem (when it's not passed as an argument) by picking the first available (and non-null) among:
- `Thread.currentThread.getContextClassLoader`
- `getClassLoader` on the class of a non-Akka stack frame up the call stack
- `ActorSystem.getClass.getClassLoader`
So that's why the above solution of mutating the context class loader works.
As to the class loader to use in practice, I got the expected behaviour with `val cl = getClass.getClassLoader` (from my build definition class) since that class loader contains all the build definition, plugins and dependencies. Also it effectively makes step 1 above behave like step 2.
In the end though, I've settled with just creating the ActorSystem by calling `ActorSystem("someName", ConfigFactory.load(cl), cl)` and not touching the context class loader, which seems somewhat cleaner (and less frightening to someone like me who does not know what the context class loader is or does)
TL;DR Instead of
val system = ActorSystem()
write
val cl = getClass.getClassLoader
val system = ActorSystem("mySystem", ConfigFactory.load(cl), cl)
Problem
I'm trying to run a rather simple HTTP POST request within a task I wrote for my SBT build, and seeing that SBT does not seem to have helpers for that, I settled on spray-client to accomplish this task. In a `project/dependencies.sbt` file I put the following: ``` 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") ``` And my task is implemented by: ``` 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() } ``` The task fails when I run it with the following exception: ``` 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) ``` My basic analysis is that the `reference.conf` file that can be found in `akka-actor_2.10-2.2.3.jar` is not read, for some reason that escapes me and maybe has something to do with how SBT manages its classpath for running the build. Some precisions: I'm on SBT 0.13.0 (hence Scala 2.10 for the build code) and I've checked that the aforementioned akka-actor jar indeed contains a reference.conf file which is as expected. When looking at what I guess might be related to the build execution classpath (`reload plugins` then `show runtime:fullClasspath` in sbt), that jar appears in the list. I also failed at googling anything relevant, being unable to convey that the problem lies with running akka from within an SBT build. In the end, I really have no idea how the 'akka' configuration key could be missing. Can anyone help?