Scala

Loading Configurations in Scala

The separation of configuration from code is a good practice that makes our system customisable as we can load different configurations according to the environment we are running it in. In this article we will describe different approaches to load configurations in Scala and how they can be combined together: loading configurations from a file, from command line parameters or from environment variables.

Configurations from a file

Let’s start with the basic case scenario: given a file, we want to read it and parse its values to use them in our code.

First, we need to define our configuration file, let’s call it application.conf.

// application.conf
my {
	secret {
		value = "super-secret"	
	}
}

We can now parse the file and use the obtained configuration in our script:

// config-tutorial.scala
import com.typesafe.config.ConfigFactory

val value = ConfigFactory.load().getString("my.secret.value")
println(s"My secret value is $value")
>> scala config-tutorial.scala 
My secret value is super-secret

By default, the ConfigFactory looks for a configuration file called application.conf. If willing to use a different configuration file (e.g.: another.conf), we just need to indicate a different file name and path to load (e.g.: ConfigFactory.load("another")). The Typesafe Config library provides several methods to make sure that the parsed value is compatible with the expected type: have a look at the Config Typesafe Documentation for methods to parse integers, longs, floats, etc.

Configurations from command line parameters

Another approach is to allow our users to redefine settings through command line parameters rather than changing the configuration file directly. All we have to do is changing our configuration file as following:

// application.conf
my {
	secret {
		value = "super-secret"
		value = ${?VALUE}	
	}
}

The output of our script will now change accordingly to the command line parameters provided.

>> scala config-tutorial.scala 
My secret value is super-secret

>> scala config-tutorial.scala -Dmy.secret.value=another-secret
My secret value is another-secret

Configurations from environment variables

Redefining configurations as part of the command line parameters works in most of the cases, but it can be tedious when we have a lot of parameters to change. Also putting sensitive information, such as passwords or tokens, in clear text in a configuration file or a run script may not be safe enough. Another option to load configurations is to inject our parameters from predefined environment variables.

In order to achieve this, we can just write a simple method that looks for a specific environment variable before loading the configurations in the previously described approach.

import scala.util.Properties

def envOrElseConfig(name: String): String = {
    Properties.envOrElse(
      name.toUpperCase.replaceAll("""\.""", "_"),
      config.getString(name)
    )
}	

Before loading our my.secret.value configuration, this simple method will first check if an environment variable called MY_SECRET_VALUE exists.

We can now put all together and create a script (gist available here) that will inject configurations in the following order:
1) From properly named environment variables
2) From command line parameters
3) From a configuration file

// application.conf
my {
	secret {
		value = "super-secret"
		value = ${?VALUE}	
	}
}
import com.typesafe.config.ConfigFactory
import scala.util.Properties

class MyConfig(fileNameOption: Option[String] = None) {
    
  val config = fileNameOption.fold(
                  ifEmpty = ConfigFactory.load() )(
                  file => ConfigFactory.load(file) )

  def envOrElseConfig(name: String): String = {
    Properties.envOrElse(
      name.toUpperCase.replaceAll("""\.""", "_"),
      config.getString(name)
    )
  }
}

The script can be used as following:

val myConfig = new MyConfig()
val value = myConfig.envOrElseConfig("my.secret.value")
println(s"My secret value is $value")

[/code]

Summary

Having a clear separation between configurations and code allow us to customise its execution to the environment where it runs in. In this article we have described different approaches of defining specific settings. In particular, we have presented a simple script that combines all these approaches in one: the script loads configurations first from environment variables, then from command line parameters and finally from a configuration file.

8 thoughts on “Loading Configurations in Scala

    1. Hi Taran, in the article I assumed you are using the standard SBT folder structure for a project: your application.conf file would be in src/main/resources. You can find an example of a project using this structure here: https://github.com/DanielaSfregola/quiz-management-service/tree/master/akka-http-crud.

      Note that MyConfig case class has an optional parameter: if the parameter is None, we will look for the application file in the standard folder (src/main/resource), otherwise we will look for the path + filename provided — see https://github.com/typesafehub/config for more information on how Config.load(file) works.

      Like

  1. Hello Daniela,
    Hope you are still monitoring the comments on this page.

    1. Can this configuration file have multiple config variables like below:
    my {
    secret {
    value = “super-secret”
    }
    secret01 {
    value = “super-secret01”
    }
    secret02 {
    value = “super-secret02”
    }
    }

    2. Does ‘application.conf’ file follow a simple json structure of definition ?
    If the answer to 1,2 is ‘yes’ then
    should there be a ‘,’ separator between these multiple values i.e., ‘secret01’ and ‘secret02’ => secret{…}, secret01{…}
    as below:
    my {
    secret {
    value = “super-secret”
    },
    secret01 {
    value = “super-secret01”
    },
    secret02 {
    value = “super-secret02”
    }
    }

    Like

    1. Hi srinivas,
      1) in the example you provided, 3 different configurations would be detected and identified by the following paths: “my.secret.value”, “my.secret01.value”, “my.secret02.value”

      2) I have personally never used a conf file in a json format, but according to the typesafe config library, it is indeed supported so you should be able to make it work. Note that the format that we are using here is not json, but a json superset. See https://github.com/typesafehub/config for more details.

      Cheers,
      Daniela

      Like

  2. Hello,

    I am using gatling to create my load tests with scala. I am passing the parameter from command line, and it is also defined in the config file.
    How can i make sure that value from the command line takes precedence over config? With the current code on your gist , i commented the config entry and it throws error saying it is not defined. Am i missing anything?
    {
    users=20
    users=${?users}
    }

    Thanks,
    Amith

    Like

  3. It’s kind of hard to search for “how to create Scala config so that environmental variables overwrite values in config file” but this is exactly what I needed! πŸ˜€ Thank you!

    Like

Leave a comment