Config parseString magic

76 views
Skip to first unread message

Derek Wyatt

unread,
May 25, 2012, 8:40:46 AM5/25/12
to Akka UserGroup
Hi guys,

I've been looking at some of the docs, and I see something that confuses me…  From the page on testing Actors:

  • implicit val system = ActorSystem("testsystem", ConfigFactory.parseString("""
  • akka.event-handlers = ["akka.testkit.TestEventListener"]
  • """))

I'm a bit lost on how this works.  From the documentation on ConfigFactory, we see:

The static methods with "load" in the name do some sort of higher-level operation potentially parsing multiple resources and resolving substitutions, while the ones with "parse" in the name just create a ConfigValue from a resource and nothing else.

So, how does the ActorSystem not fall on its face?  It looks like the Config parameter to the ActorSystem is going to contain only one value, and so all of the other configuration that it's going to need is going to wind up not being defined and exceptions being thrown.

I would have expected that this was the only viable thing to do (modified from the page on configuration):

  • val customConf = ConfigFactory.parseString("""
  • akka.event-handlers = ["akka.testkit.TestEventListener"]
  • """)
  • // ConfigFactory.load sandwiches customConfig between default reference
  • // config and default overrides, and then resolves it.
  • val system = ActorSystem("MySystem", ConfigFactory.load(customConf))

 Since "load()'" is going to pull in the rest of the configuration.

What is the "right" way to specialize a configuration at ActorSystem instantiation?
signature.asc

√iktor Ҡlang

unread,
May 25, 2012, 8:43:48 AM5/25/12
to akka...@googlegroups.com
This is how it is done internally:  

final val config: Config = {
      val config = cfg.withFallback(ConfigFactory.defaultReference(classLoader))
      config.checkValid(ConfigFactory.defaultReference(classLoader), "akka")
      config
    }

So it's always falling back to the references.

Cheers,
--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Derek Wyatt

unread,
May 25, 2012, 8:45:05 AM5/25/12
to akka...@googlegroups.com
Thx.  So either way would be the "right" way and one can choose whatever they like best.  Looks good.

Cheers,
D

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

signature.asc

√iktor Ҡlang

unread,
May 25, 2012, 8:52:01 AM5/25/12
to akka...@googlegroups.com
On Fri, May 25, 2012 at 2:45 PM, Derek Wyatt <de...@derekwyatt.org> wrote:
Thx.  So either way would be the "right" way and one can choose whatever they like best.  Looks good.

Yeah, it's worked out pretty well imho

Havoc Pennington

unread,
May 27, 2012, 4:08:58 PM5/27/12
to akka...@googlegroups.com
Hi,

On Fri, May 25, 2012 at 8:45 AM, Derek Wyatt <de...@derekwyatt.org> wrote:
> Thx.  So either way would be the "right" way and one can choose whatever
> they like best.  Looks good.
>

I would argue that doing only the parseString is bad.

1. ConfigFactory.load supports system property overrides
(-Dfoo.bar=whatever) for config settings.

2. With only the parseString (or parseWhatever), if you have any
substitutions (the ${} syntax in the config file), the reference
config is not present for resolving the ${}.

3. If the "root" main() method of an app creates a complete config, it
can pass that down to any and all libraries such as Akka, and it won't
need to be modified or copied by each library. (The withFallback code
in ActorSystem will no-op, after wasting some CPU, if the config is
already complete.)

4. If you have one config for the whole app, the config for each
library can refer to config settings for other libs, or you can have
app-wide config settings. Each lib is not isolated in its own little
world.

5. ConfigFactory.load may be slightly more future-proof, for example
new ways to override or provide defaults could appear in a future
version.

These issues may or may not make an immediate practical difference for
a particular app. But as far as "what's recommended," my view is that
you should pass in a complete config (including reference config) to
ActorSystem.

In some sense the
"cfg.withFallback(ConfigFactory.defaultReference(classLoader))" in
ActorSystem is papering over apps that don't follow best practices. If
that line weren't present, the checkValid following would throw an
exception complaining about missing defaults. I think it would be
legitimate for Akka to have done that instead, and the sample provided
at https://github.com/typesafehub/config/blob/master/examples/simple-lib/src/main/scala/simplelib/SimpleLib.scala
does throw an exception here. Akka is just trying to be nice and
rescue suboptimal apps ;-)

If you want to add a couple settings in code with parseString or
parseMap, I would suggest the approach described in "Reading
configuration from a custom location" in the docs snapshot:

http://doc.akka.io/docs/akka/snapshot/general/configuration.html

(the current release 2.0.1 docs don't have that section)

If you use ConfigFactory.load() with no parameters and then merge your
in-code settings with that, you retain the ability to specify
-Dconfig.file etc. on the command line ... if you use
ConfigFactory.load(something), then you replace the default (which is
-Dconfig.{file,resource,url} or if those are not present,
application.conf on classpath).

Havoc

Derek Wyatt

unread,
May 27, 2012, 4:27:01 PM5/27/12
to akka...@googlegroups.com
Okee doke. I'm not really in much of a position to argue one way or the other :)

For me, there are two different examples in the Akka docs:

http://doc.akka.io/docs/akka/2.0.1/scala/testing.html#Expecting_Exceptions

and the configuration doc:

http://doc.akka.io/docs/akka/snapshot/general/configuration.html (what you already mentioned)

I saw this as a discrepancy, but then found that they're both pretty much the same. I get that the "configuration" example is more "correct" in a pure sense, but it's going to be confusing if there are two that aren't actually equivalent in real life. One could say that the "testing" one isn't the real world scenario, so we can be more relaxed about it, but if my test succeeds when it would in the "real world" then it's not a good test.

I'm happy with whatever. I just couldn't see how the testing version really worked. But if you're saying that the testing one isn't "good" then it might be nice to see the docs changed to match the method used in the configuration section.

Regs,
Derek
signature.asc

Havoc Pennington

unread,
May 27, 2012, 5:30:31 PM5/27/12
to akka...@googlegroups.com
On Sun, May 27, 2012 at 4:27 PM, Derek Wyatt <de...@derekwyatt.org> wrote:
> Okee doke.  I'm not really in much of a position to argue one way or the other :)
>

I'm just being completist / pedantic for the list archives, I freely
admit this doesn't matter too much in many cases. Your question is a
good one.

The testing example is a little pesky since the "correct" way is
somewhat verbose and would clutter up that example... so maybe we
should think about a nice ConfigFactory convenience method that takes
a string or Map and merges it with the default config... I do get a
sense that a lot of people end up wanting to set a couple of values in
code. It needs some thought.

Havoc
Reply all
Reply to author
Forward
0 new messages