Open bespalovdn opened 9 years ago
Any updates here ? I'm running into an issue where my src/main/resources/reference.conf
doesn't take effect and have no clue till I see this thread. I wonder why users' reference.conf
don't take precedence
I don't know of a real answer here. The design intent is to have application.conf separate from reference.conf specifically so it can be ordered on top. For resources with the same name, they are kept in the order the class loader returns them, but afaik there are no strong guarantees about that. The same key really isn't supposed to be in multiple reference.conf.
"users" here actually means the library built on Akka. A typical configuration is akka.actor.provider=akka.remote.RemoteActorRefProvider
for akka remoting to work. If we put configurations in application.conf
, then the end users' application.conf
may not take effect.
There's no way to determine "user's reference.conf" they're all on classpath, it depends on order of loading stuff.
If you build middleware introduce your own config and load it like application.conf withFallback reference-overrides.conf withFallback reference.conf
, just like Play does.
reference.conf is just that, reference, and any aproach to make it layered built-in will cause the same kind of issue on the layer you've just added. Thus the solution is to document how to load configs.
I propose this should be closed.
I can imagine some useful docs to add in this area (describing a solution like Play's?). Putting an application.conf in the library may also work in practice, since the application's own application.conf would probably be first on classpath in most cases, but I'm not 100% confident about that. I would put most library settings in reference.conf still and only the "overrides" in application.conf if trying that.
I can imagine some useful docs to add in this area (describing a solution like Play's?).
Yeah, sounds like this could be a docs ticket.
Putting an application.conf in the library may also work in practice, since the application's own application.conf would probably be first on classpath in most cases, but I'm not 100% confident about that. I would put most library settings in reference.conf still and only the "overrides" in application.conf if trying that.
It would work for cases where no other application.conf wants to override given setting. But then you locked out people from changing that setting basically, since the ordering of "end user application.conf" with rehards to "library application.conf" is undefined again - so I would not recommend that to anyone..
Technically a "middle-man.conf" could override reference and be allowed to be overriden by application.conf - which would basically be codifying what play has been doing... We could I guess introduce a blessed name for the "middle-man"..?
@ktoso Are you referring to https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/Configuration.scala#L35 ?
Yes, as I said, they do:
val combinedConfig: Config = Seq(
systemPropertyConfig,
directConfig,
applicationConfig,
playOverridesConfig,
referenceConfig
).reduceLeft(_ withFallback _)
I think it would be helpful to detect and warn or fail on an overwrite within the same "layer".
Right now, conflicts can sometimes work by coincidence depending on the classpath order, and then fail in production in a surprising way because of an incidental change in classpath order.
could warn in one of the -Dconfig.trace modes which could be useful. we have a rule against printing anything by default (because if we do that with println people can’t control it, and we don’t depend on a log framework), so we only print warnings when the trace flags are turned on.
Right now, conflicts can sometimes work by coincidence depending on the classpath order, and then fail in production in a surprising way because of an incidental change in classpath order.
This just happened to me and it is super annoying.
Currently, working plan is to install a java agent such that classloader.getResources
returns the enumeration in the order I want, using https://stackoverflow.com/a/31727841/5266 as a guide.
Numbered ordering scheme would work better...
Having a consistent ordering would be helpful to eliminate production-only surprises, but I think there's still a fundamental underlying issue. Having multiple reference.conf
files that define the same property is not really a valid configuration, and even if the order were deterministic, it might not be what a particular application wants. The ambiguity needs to be detected and resolved in application.conf
.
I guess we could order on content hashing? This does not mean to make the problem to go away, but at least it would not be non-reproducable on the same set of dependencies.
Some code to reference from our library:
val referenceOverrides =
ConfigFactory.parseResources("your-reference-overrides.conf")
val config =
ConfigFactory.load(ConfigFactory.defaultApplication().withFallback(referenceOverrides))
FYI, I fixed this by adding a byte-buddy agent and rewriting the calls to ConfigFactory.load
.
I think it worth to mention in documentation, about how to control the order of
reference.conf
files merging, when you initialize your configuration. For instance, commonly used libraryakka-actor
have own configuration inreference.conf
. I've created a library, that hardly usesakka-actor
and redefines some of theirs configuration in ownreference.conf
. Then I try to get them both merged onConfigFactory.load()
. But there is no guarantee in which order thosereference.conf
s will be read from resources. I did some investigation before came up with solution. Here is corresponding question on stackoverflow: http://stackoverflow.com/questions/31698605/hocon-multiple-reference-conf-resolution-issue/31727841 Please, consider to mention in your documentation about how to control the order ofreference.conf
s merging.Thanks!