scf37 / config3   1.0.6

Apache License 2.0 GitHub

Configuration library for Scala

Scala versions: 3.x 2.13 2.12

Config3

This is small configuration library for Scala utilizing Typesafe Config.

Design

  • use typesafe config as backend
  • ability to fail when provided config key is unknown/misspelled
  • ability to print help on available parameters
  • ability to define required and optional parameters
  • ability to load parameters from: cmd line arguments, env, java props, files (typesafe)
  • ability to print loaded parameters with origins on startup

Example output

Help on available parameters

This is myapp project
Parameters:

Name                  Value         Description
myapp.env                           environment to use. Try "dev" or "prod"
                                    if no env specified, things will go horribly wrong!
myapp.list            [1,2,3]       the list
myapp.listmap         [a=1,a=2,b=3] the listmap
myapp.map.value                     required map parameter
myapp.storage_root    "./files"     file storage root
myapp.web.dev         true          enable development mode
myapp.web.password                  application password

Loaded parameters with origins

myapp.env            "dev"                    system properties: 1
myapp.list           [1,2,3]                  reference.conf @ file:/opt/app/conf/reference.conf: 30
myapp.listmap        [{"a":1},{"a":2},{"b":3}]reference.conf @ file:/opt/app/conf/reference.conf: 33
myapp.map.value      {"x":1,"y":2,"z":3}      system properties: 2
myapp.storage_root   "./files"                reference.conf @ file:/opt/app/conf/reference.conf: 10
myapp.web.dev        true                     reference.conf @ file:/opt/app/conf/reference.conf: 20
myapp.web.password   ******                   system properties: 3

Usage

Update build.sbt

libraryDependencies += "me.scf37" %% "config3" % "1.0.6"

Define reference.conf

reference.conf contains known configuration keys along with defaults and descriptions.

Example:

#application description
#it will be shown on help screen
myapp {
  #application port with default value 8080
  port = 8080
  
  #environment name, required parameter, must be provided
  env = null
}

Write some code

import com.typesafe.config.ConfigFactory
import me.scf37.config3.Config3

object Main {
  def main(args: Array[String]): Unit = {
    // load reference configuration
    // ConfigFactory.defaultReference() includes system properties and therefore unwanted
    val reference = ConfigFactory.parseResources("reference.conf")

    // there can be many reference.conf classpath-wise so we process keys for our application only
    def isAppConfigKey(key: String) = key.startsWith("myapp.")

    // print help if --help requested
    if (args.sameElements(Seq("--help"))) {
      println(Config3.help(reference, isAppConfigKey))
      System.exit(1)
    }

    // parse command line args -<arg name> <arg value>
    val cmdlineConfig = Config3.parse(args) match {
      case Left(error) =>
        println(error)
        System.exit(2)
        ???
      case Right(config) => config
    }

    // load config, falling back to system properties, environment, myapp.conf and reference config
    val config =
      cmdlineConfig
        .withFallback(ConfigFactory.systemProperties())
        .withFallback(ConfigFactory.systemEnvironment())
        .withFallback(ConfigFactory.load("myapp.conf"))
        .withFallback(reference)

    // ensure all required parameters are set and we have no unknown/misspelled keys starting with myapp.
    val errors = Config3.validate(reference, config, isAppConfigKey)
    if (errors.nonEmpty) {
      errors.foreach(println)
      System.exit(2)
    }

    // print resolved configuration
    println(Config3.printConfig(reference, config, isAppConfigKey, _.contains("password")))
  }
}

Also see me.scf37.config3.Config3Main