Search code examples
javaconfigurationakkatypesafe-config

Is it possible to non-programmatically merge config objects that are at different hierarchical levels?


I'm using TypeSafe Config. Imagine I want to have application wide defaults for resilience patterns but override them specifically at lower config level. I would prefer to have a generic solution instead of manually coding the config creation for each and every stream. Please see example configs:

application.conf

application {
  streams {
    retry {
      attempts = 100
      poll-interval = 5s
      minBackoff = 200 ms
      maxBackoff = 2s
      randomFactor = 0.25
    }
  }
}

service1.conf

application {
  streams {
    stream1 {
      retry {
        attempts = 2
      }
    }
    stream2 {
      retry {
        poll-interval = 5s
      }
    }
  }

Is there a way to non-programmatically merge these configs? Use the defaults from application.conf and override if the value exists in the lower level?

What's the best practice here?

I can't use:

var defaultConf = ConfigFactory.load("application.conf");
var conf = ConfigFactory.load("service1.conf").withFallback(defaultConf);

Because the configs are not at the same hierarchical level.


Solution

  • In general I agree with Ivan and the link to his other answer regarding reference configs. (Or any type of base config.)

    The part that I think you are missing is the "hierarchy". You can do that, in a non-programmatic way, using inheritance. Here is the docs: https://github.com/lightbend/config#inheritance . You can have a generic config in your reference and then inherit and override in your hierarchy. The docs have an example very similar to yours.

    The gist would be to reference the generic config with something like:

    application.streams.stream1 = ${application.streams}
    application.streams.stream1.retry.attempts = 2
    
    application.streams.stream2 = ${application.streams}
    application.streams.stream2.retry.poll-interval = 5s