Domanda

I want to resolve one Config object, say config1 with other, say config2.

The only public API that allows something of the sort is config1.withFallback(config2).resolve(). However this adds entries from config2 to config1 which is not something we want.

On some investigation, we found a non-public class named ResolveContext which provides a method for that. So we are making use of that using reflection. Our current code:

object ConfigImplicits {
  implicit class RichConfig(val config: Config) extends AnyVal {
    def resolveWith(source: Config): Config = {
      val resolver = resolveContext.getDeclaredMethod(
        "resolve", 
        abstractConfigValue, 
        abstractConfigObject, 
        configResolveOptions
      )
      resolver.setAccessible(true)
      resolver.invoke(
        null,
        config.underlyingAbstractConfigObject,
        source.underlyingAbstractConfigObject,
        ConfigResolveOptions.defaults
      ).asInstanceOf[ConfigObject].toConfig
    }

    def underlyingAbstractConfigObject = {
      val f = simpleConfig.getDeclaredField("object")
      f.setAccessible(true)
      f.get(config)
    }
  }

  val resolveContext = Class forName "com.typesafe.config.impl.ResolveContext"
  val abstractConfigValue = Class forName "com.typesafe.config.impl.AbstractConfigValue"
  val abstractConfigObject = Class forName "com.typesafe.config.impl.AbstractConfigObject"
  val configResolveOptions = classOf[ConfigResolveOptions]
  val simpleConfig = Class forName "com.typesafe.config.impl.SimpleConfig"
}

We realize that relying on non-public innards might not be a good idea. So:

  1. Is there a public method, that we somehow missed, which already does this?
  2. If not, shall we make a pull request?
È stato utile?

Soluzione

There is not AFAIK a public method. A less-fragile workaround instead of relying on private API might be to first resolve with your source object in there as a fallback, then iterate over the keys in the source object you resolved from and just remove those unwanted keys from the target object.

I can't think of a reason not to add a Config.resolveWith(), though I wonder if there was a reason since I do remember considering it. Maybe I just figured nobody would use it.

If you do a pull request, be sure to include tests and docs. I think the pull request is reasonable, assuming it turns out to be very little code (as I would expect). The current master branch is open for API additions, to appear in an eventual 1.2 release.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top