Merging multiple TypeSafe Config files and resolving only after they are all merged

John Arrowwood picture John Arrowwood · Mar 3, 2016 · Viewed 11.5k times · Source

I am writing test code to validate a RESTful service. I want to be able to point it at any of our different environments by simply changing an environment variable before executing the tests.

I want to be able to merge three different config files:

  • conf/env/default.conf - the default configuration values for all environments
  • conf/env/<env>.conf - the environment-specific values
  • application.conf - the user's overrides of any of the above

The idea is that I don't want everything in a single config file, and run the risk of a bad edit causing configuration items to get lost. So instead, keep them separate and give the user the ability to override them.

Here's where it gets tricky: default.conf will include ${references} to things that are meant to be overridden in <env>.conf, and may be further overridden in application.conf.

I need to postpone resolving until all three are merged. How do I do that?

Answer

John Arrowwood picture John Arrowwood · Mar 7, 2016

The answer is to use ConfigFactory.parseResource() in place of ConfigFactory.load().

Here is the finished result

private lazy val defaultConfig     = ConfigFactory.parseResources("conf/env/default.conf")
private lazy val environmentConfig = ConfigFactory.parseResources("conf/env/" + env + ".conf" )
private lazy val userConfig        = ConfigFactory.parseResources("application.conf")
private lazy val config = ConfigFactory.load()
                          .withFallback(userConfig)
                          .withFallback(environmentConfig)
                          .withFallback(defaultConfig)
                          .resolve()