Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prohibit resolving during loading in typesafe config

I want to prohibit resolving of a.b. I want to substitute param from another config. Like this:

val d = ConfigFactory.load(ConfigFactory.parseString(
    """
      |param = x
      |a.b = ${param}
    """.stripMargin))

val a = ConfigFactory.parseString("param = 1")

val result = a.withFallback(d).resolve()

In this case param gets value 1, but a.b remains x I've tried to set ConfigResolveOptions.defaults().setAllowUnresolved(true) when loading config d, but that doesn't work.

How can I overcome this?

like image 975
maks Avatar asked May 08 '15 17:05

maks


3 Answers

The problem is that Config.load is resolving the substitution immediately. If you take that out it resolves like you want it to:

val p = ConfigFactory.parseString(
  """
    |param = x
    |a.b = ${param}
  """.stripMargin)

val a = ConfigFactory.parseString("param = 1")

val result = a.withFallback(p).resolve()

println(result.getString("a.b"))

This prints 1.

You don't need to use Config.load unless you want to use reference.conf, etc. If you do want to use Config.load then you should do it after you have composed all the configs together using withFallback.

For example, this also prints 1:

  val p = ConfigFactory.parseString(
    """
      |param = x
      |a.b = ${param}
    """.stripMargin)

  val d = ConfigFactory.load(p)
  val a = ConfigFactory.parseString("param = 1")

  val result = a.withFallback(p)
  val loaded = ConfigFactory.load(result)
  println(loaded.getString("a.b"))

Or, say you have an application.conf with include that you want to use with ConfigFactory.load() (per your comment).

If application.conf looks like

include "foo"

and foo.conf looks like

a.b = ${param}

then this prints 1 also:

  val a = ConfigFactory.parseString("param = 1")  

  val app = ConfigFactory.load("application", ConfigParseOptions.defaults,
    ConfigResolveOptions.defaults.setAllowUnresolved(true))

  val result = a.withFallback(app).resolve

  println(result.getString("a.b"))

In general, if you want A to override B to override C then you should use A.withFallback(B).withFallback(C).

like image 83
sourcedelica Avatar answered Nov 15 '22 03:11

sourcedelica


I struggled a bit with the same thing: trying to use "fallbacks" to override values, when it was designed for layering/merging configs

Assuming I understand your use case, I recommend instead using file includes.

In my application.conf I have the default value

a.b = "placeholder"

And at the bottom I have the following include

# Local overrides - for development use
include "local.conf"

And finally in local.conf

param = 1
a.b = ${param}

The end result is that a.b will be overridden with 1

like image 44
noahlz Avatar answered Nov 15 '22 05:11

noahlz


Found a workaround for my problem:

So If I have config file application.conf which uses include to include config files which contain substitution syntax and files which contain declaration of the config values which are going to be substituted.

val a = ConfigFactory.parseString(s"""param = 1""")
 val z = ConfigFactory.parseResources("application.conf") //this doesn't resolve substitutions

val result = a.withFallback(z).resolve().withFallback(ConfigFactory.load("application.conf"))
like image 44
maks Avatar answered Nov 15 '22 04:11

maks