HOCON: multiple reference.conf resolution issue
Asked Answered
L

1

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.

Lareelareena answered 29/7, 2015 at 11:2 Comment(4)
Can you provide an example of your config that you are trying to load and the code you are using to load it?Parcenary
@Parcenary 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.Lareelareena
When I want to override standard conf from akka, I do it via application.conf and not reference.confParcenary
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.Willwilla
L
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.

Lareelareena answered 30/7, 2015 at 15:22 Comment(2)
How did you manage to arrange resources in this method? Do you rely on URL's getPath method?Inesinescapable
@Inesinescapable 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.Lareelareena

© 2022 - 2024 — McMap. All rights reserved.