Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interpolation within array contantenation does not always work #339

Open
adamhonen opened this issue Jul 22, 2015 · 3 comments
Open

Interpolation within array contantenation does not always work #339

adamhonen opened this issue Jul 22, 2015 · 3 comments

Comments

@adamhonen
Copy link

Trying to load configuration from a file that has the following :

some_array = []
some_array += {
    replaced_a = ${replacement_a}
}
some_array += {
    replaced_b = ${replacement_b}
}

Where replacement_a & replacement_b are provided via another configuration object (I use configFromClasspath.resolveWith(anotherConfig, ConfigResolveOptions.defaults()))
I get com.typesafe.config.ConfigException$NotResolved: called unwrapped() on value with unresolved substitutions, need to Config#resolve() first, see API docs

But when I modify the configuration to:

workaround_a {
  name=${replacement_a}
  prop = "aaa"
}

workaround_b = {
  name=${replacement_b}
  prop = "bbb"
}

some_array = [${workaround_a},${workaround_b}]

It works fine.
Also I see no issues when parsing the configuration String directly.

@adamhonen
Copy link
Author

Naming the first configuration as arrayInterpolation.conf and naming the second as arrayInterpolationWorkaround, I’ve written the following test that shows this:

import java.util.HashMap

import org.junit.Test

import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import com.typesafe.config.ConfigResolveOptions

class ArrayInterpolationTest extends TestUtils {

    def getExternalConfig(): Config = {
        val base = new HashMap[String, String]()
        base.put("replacement_a", "a");
        base.put("replacement_b", "b");
        return ConfigFactory.parseMap(base)
    }

    @Test
    def interpolationWithinArrayConcatenation(): Unit = {
        val externalConfig = getExternalConfig()

        verifyFrom(externalConfig, "arrayInterpolation")
    }

    @Test
    def interpolationWithinArrayDefinition(): Unit = {
        val externalConfig = getExternalConfig()

        verifyFrom(externalConfig, "arrayInterpolationWorkaround")
    }

    def verifyFrom(externalConfig: Config, confFile: String): Unit = {
        val fromClasspath = ConfigFactory.load(confFile, ConfigParseOptions.defaults(), ConfigResolveOptions.defaults().setAllowUnresolved(true))
        val withSubstiturions = fromClasspath.resolveWith(externalConfig, ConfigResolveOptions.defaults())
        val config = externalConfig.withFallback(withSubstiturions).resolve()
    }
}

@havocp
Copy link
Collaborator

havocp commented Jul 22, 2015

So there was a bug in toString of ConfigDelayedMerge, which created a misleading error message. I just fixed that on master. With that fixed, we get the correct error message and this turns out to be the same problem as #332 I believe.

[error] Test com.typesafe.config.impl.ArrayInterpolationTest.interpolationWithinArrayConcatenation failed: com.typesafe.config.ConfigException$BugOrBroken: replace in parent not possible ConfigDelayedMerge([],[{"replaced_a":${replacement_a}}],[],[{"replaced_a":${replacement_a}}][{"replaced_b":${replacement_b}}]) with ConfigDelayedMerge([],[{"replaced_a":${replacement_a}}]) in ResolveSource(root=SimpleConfigObject({"replacement_a":"a","replacement_b":"b"}), pathFromRoot=null), took 0.003 sec
[error]     at com.typesafe.config.impl.ResolveSource.replaceWithinCurrentParent(ResolveSource.java:245)
[error]     at com.typesafe.config.impl.ConfigDelayedMerge.resolveSubstitutions(ConfigDelayedMerge.java:110)
[error]     at com.typesafe.config.impl.ConfigDelayedMerge.resolveSubstitutions(ConfigDelayedMerge.java:59)
[error]     at com.typesafe.config.impl.ResolveContext.realResolve(ResolveContext.java:179)
[error]     at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:142)
[error]     at com.typesafe.config.impl.SimpleConfigObject$ResolveModifier.modifyChildMayThrow(SimpleConfigObject.java:379)
[error]     at com.typesafe.config.impl.SimpleConfigObject.modifyMayThrow(SimpleConfigObject.java:312)
[error]     at com.typesafe.config.impl.SimpleConfigObject.resolveSubstitutions(SimpleConfigObject.java:398)
[error]     at com.typesafe.config.impl.ResolveContext.realResolve(ResolveContext.java:179)
[error]     at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:142)
[error]     at com.typesafe.config.impl.ResolveContext.resolve(ResolveContext.java:231)
[error]     at com.typesafe.config.impl.SimpleConfig.resolveWith(SimpleConfig.java:74)
[error]     at com.typesafe.config.impl.SimpleConfig.resolveWith(SimpleConfig.java:37)
[error]     at com.typesafe.config.impl.ArrayInterpolationTest.verifyFrom(ArrayConcatTest.scala:35)
[error]     at com.typesafe.config.impl.ArrayInterpolationTest.interpolationWithinArrayConcatenation(ArrayConcatTest.scala:30)
[error]  
...

@havocp
Copy link
Collaborator

havocp commented Jul 22, 2015

Here's a version of the test case without any external files:

    val replacements = ConfigFactory.parseString("""
  replacement_a = a
  replacement_b = b
""")

    val arrayInterpolation = """
  some_array = []
  some_array += {
    replaced_a = ${replacement_a}
  }
  some_array += {
    replaced_b = ${replacement_b}
  }
"""

    @Test
    def interpolationWithinArrayConcatenation(): Unit = {
        val fromClasspath = ConfigFactory.load(ConfigFactory.parseString(arrayInterpolation, ConfigParseOptions.defaults()), ConfigResolveOptions.defaults().setAllowUnresolved(true))
        val withSubstitutions = fromClasspath.resolveWith(replacements, ConfigResolveOptions.defaults())
        val config = replacements.withFallback(withSubstitutions).resolve()
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants