9

I have multi-module project under SBT.

Project A (library) has reference.conf file with A's configuration parameters. Project A depends on akka-actor library, which ships with its own reference.conf file. Project A redefines some akka's parameters in own reference.conf.

Project B depends on A.

When I call ConfigFactory.load() in B, I'm getting wrong order of reference.confs merging. It first takes A's config, then applies akka-actor's config over it. Eventually, I'm getting initial akka-actor's configuration.

How can I fix it? I need to get akka-actor's config loaded first, then my A's config should be applied over it.

Dmitry Bespalov
  • 5,179
  • 3
  • 26
  • 33
  • Can you provide an example of your config that you are trying to load and the code you are using to load it? – cmbaxter Jul 29 '15 at 11:21
  • @cmbaxter There is too much code to demonstrate. But nothing special. I suppose it's common behavior of `ConfigFactory.load()`. Documentation claims: it will apply all `reference.conf` files in classpath. But it didn't specify in what order. I'm looking the way how to specify concrete order of application `reference.conf` files. – Dmitry Bespalov Jul 29 '15 at 13:28
  • When I want to override standard conf from akka, I do it via application.conf and not reference.conf – cmbaxter Jul 29 '15 at 13:45
  • 2
    I would think that `reference.conf` is for the applications own configuration, not for **overriding** configuration in a transient dependency library. As I recall it there are no guarantees about class path ordering, so you can probably not protect against it in any other way than to override settings elsewhere. – johanandren Jul 30 '15 at 09:34

1 Answers1

10

Ok, looks like I've found the answer in sources of ConfigFactory.

All the reference.conf is being loaded through ClassLoader.getResources. It returns java.util.Enumeration[URL]. The order of URLs in this enum is the answer to the question. So all you need to do: ensure the order of your reference.conf resources in this enumeration properly arranged.

Here is an example of how to do that. First, create your own version of ClassLoader by overriding getResources method:

import scala.collection.JavaConverters._

class CustomClassLoader(loader: ClassLoader) extends ClassLoader(loader){
    override def getResources(name: String): util.Enumeration[URL] = {
        val resources = super.getResources(name).asScala.toList
        // arrange resources as you wish here
        java.util.Collections.enumeration(resources.asJava)
    }
}

Last, call load method of ConfigFactory with your CustomClassLoader instance.

Dmitry Bespalov
  • 5,179
  • 3
  • 26
  • 33
  • How did you manage to arrange resources in this method? Do you rely on URL's `getPath` method? – maks Jan 10 '17 at 02:02
  • @maks I've figured out the order to load config files. Then I've arranged the list of resources according to that order. That's it. And yes, I'd relied on URL which contains name and path to the config files. – Dmitry Bespalov Jan 10 '17 at 06:33