DOC: add subtree lifting tricks for config
Would be nice to put some of these tips in the config docs. WDYT?
--
Jonas Bonér
CTO
Typesafe - The software stack for applications that scale
Phone: +46 733 777 123
Twitter: @jboner
Blog: letitcrash.com
---------- Forwarded message ----------
From: "Havoc Pennington" <hp@pobox.com>
Date: Feb 8, 2012 4:38 AM
Subject: Re: [akka-user] reference.conf conflicts in fat jar (I think)
To: <akka-user@googlegroups.com>
Hi,
On Tue, Feb 7, 2012 at 9:44 PM, Josh Marcus <jmarcus@azavea.com> wrote:
> It's actually the case that my library does currently redefine
> configuration parameters. I'm using your config file library, and users of
> my library can override parameters using their own application.conf. But I
> have akka configuration parameters that I need to set for all users, so I
> override akka configuration in my library's reference.conf. Do you have an
> alternate suggestion?
>
Without knowing the particulars, you may be able to use the "lift a
subtree" approach.
Say your library is "foo", do this:
foo {
akka {
// your akka stuff here, matching akka's normal config file
}
// your other foo-specific settings
whatever = something
bar = baz
}
Now, copying the simple-lib example,
https://github.com/typesafehub/config/blob/master/examples/simple-lib/src/main/scala/simplelib/SimpleLib.scala
you might have a constructor for your library's main object or
whatever that takes a Config. In there you lift up your foo-specific
akka config and then provide it to Akka:
class FooContext(config: Config) {
val system = new ActorSystem("Foo",
config.getConfig("foo").withFallback(config))
}
That is the general idea anyway. So foo.akka.* is now just akka.*, for
purposes of your ActorSystem. But for someone else's actor system, you
won't be messing with akka.*
Also, in application.conf, people can now separately configure akka.*
and foo.akka.* depending on their intent.
One somewhat lame feature of the above is that foo.whatever and
foo.akka were both "lifted out" by getConfig("foo"), so in the final
config, a toplevel "whatever" exists identical to "foo.whatever",
which is namespace pollution. Not the end of the world but could cause
trouble. At the moment you'd have to fix that by hand-building a
Config object containing foo.akka as just akka, and I don't think
there's a very nice API for that in the config lib. It might be nice
to have a Config.filter or other API in the library that would fix
this, in Scala it could be
config.getConfig("foo").filter({ kv => kv._1 == "akka" })
but since it's a Java library I'm not sure. Maybe just a hardcoded
"filterPath(String pathToKeep)" kind of thing, or just methods to add
parent/child nodes.
val akkaOverrides = ConfigFactory.empty().put("akka", getConfig("foo.akka"))
("put" doesn't work since it conflicts with j.u.Map though)
Another thing that could be tricky in the above pattern is that system
properties are in "config" already, so if someone specifies a system
property -Dakka.something, but in the config file there's a
foo.akka.something, the foo.akka.something will always end up
overriding the -Dakka.something for purposes of library foo. Whether
this is a bug or a feature probably varies by context. You could
change the behavior by adding the overrides again on top:
ConfigFactory.defaultOverrides().withFallback(config.getConfig("foo").withFallback(config))
I'm not sure whether to suggest doing that or not, fortunately it
probably doesn't matter that much in practice.
This is a pattern I'm hoping will work well, since we had it in mind
when designing the config lib. But if it doesn't maybe we will need
more ideas...
Havoc
--
Jonas Bonér
CTO
Typesafe - The software stack for applications that scale
Phone: +46 733 777 123
Twitter: @jboner
Blog: letitcrash.com
---------- Forwarded message ----------
From: "Havoc Pennington" <hp@pobox.com>
Date: Feb 8, 2012 4:38 AM
Subject: Re: [akka-user] reference.conf conflicts in fat jar (I think)
To: <akka-user@googlegroups.com>
Hi,
On Tue, Feb 7, 2012 at 9:44 PM, Josh Marcus <jmarcus@azavea.com> wrote:
> It's actually the case that my library does currently redefine
> configuration parameters. I'm using your config file library, and users of
> my library can override parameters using their own application.conf. But I
> have akka configuration parameters that I need to set for all users, so I
> override akka configuration in my library's reference.conf. Do you have an
> alternate suggestion?
>
Without knowing the particulars, you may be able to use the "lift a
subtree" approach.
Say your library is "foo", do this:
foo {
akka {
// your akka stuff here, matching akka's normal config file
}
// your other foo-specific settings
whatever = something
bar = baz
}
Now, copying the simple-lib example,
https://github.com/typesafehub/config/blob/master/examples/simple-lib/src/main/scala/simplelib/SimpleLib.scala
you might have a constructor for your library's main object or
whatever that takes a Config. In there you lift up your foo-specific
akka config and then provide it to Akka:
class FooContext(config: Config) {
val system = new ActorSystem("Foo",
config.getConfig("foo").withFallback(config))
}
That is the general idea anyway. So foo.akka.* is now just akka.*, for
purposes of your ActorSystem. But for someone else's actor system, you
won't be messing with akka.*
Also, in application.conf, people can now separately configure akka.*
and foo.akka.* depending on their intent.
One somewhat lame feature of the above is that foo.whatever and
foo.akka were both "lifted out" by getConfig("foo"), so in the final
config, a toplevel "whatever" exists identical to "foo.whatever",
which is namespace pollution. Not the end of the world but could cause
trouble. At the moment you'd have to fix that by hand-building a
Config object containing foo.akka as just akka, and I don't think
there's a very nice API for that in the config lib. It might be nice
to have a Config.filter or other API in the library that would fix
this, in Scala it could be
config.getConfig("foo").filter({ kv => kv._1 == "akka" })
but since it's a Java library I'm not sure. Maybe just a hardcoded
"filterPath(String pathToKeep)" kind of thing, or just methods to add
parent/child nodes.
val akkaOverrides = ConfigFactory.empty().put("akka", getConfig("foo.akka"))
("put" doesn't work since it conflicts with j.u.Map though)
Another thing that could be tricky in the above pattern is that system
properties are in "config" already, so if someone specifies a system
property -Dakka.something, but in the config file there's a
foo.akka.something, the foo.akka.something will always end up
overriding the -Dakka.something for purposes of library foo. Whether
this is a bug or a feature probably varies by context. You could
change the behavior by adding the overrides again on top:
ConfigFactory.defaultOverrides().withFallback(config.getConfig("foo").withFallback(config))
I'm not sure whether to suggest doing that or not, fortunately it
probably doesn't matter that much in practice.
This is a pattern I'm hoping will work well, since we had it in mind
when designing the config lib. But if it doesn't maybe we will need
more ideas...
Havoc
Leave a comment
on 2012-03-05 15:41 *
By rk@rkuhn.info
(In revision:56ce7a0ecd9107bdaef7be31ef18663f6829494f) rewrite configuration.rst, see #1823 and #1838
Branch: wip-config-docs-∂π
Branch: wip-config-docs-∂π
on 2012-03-05 23:29 *
By rk@rkuhn.info
(In revision:be50090d66e97072d1b66626c124ea47cb5a3a7f) rewrite configuration.rst, see #1823 and #1838
Branch: release-2.0
Branch: release-2.0