What is a good way to set up a project in Scala which uses different configuration depending on environments.
I need to specifically have different databases for development, test and production environment (similar to what is done in Rails)
Configurations from a file 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.
Typesafe Config allows you to store configuration into separated files and use include keyword to include configuration of those files.
An application configuration file is an XML file used to control assembly binding. It can redirect an application from using one version of a side-by-side assembly to another version of the same assembly. This is called per-application configuration.
Another strategy I'm using consists of using includes.
I usually store my DEV settings in the default application.conf
file then I create a new conf file for other environments and include the default one.
Let's say my DEV conf application.conf
looks like this:
myapp {
server-address = "localhost"
server-port = 9000
some-other-setting = "cool !"
}
Then for the PROD, I could have another file called prod.conf
:
include "application"
# override default (DEV) settings
myapp {
server-address = ${PROD_SERVER_HOSTNAME}
server-port = ${PROD_SERVER_PORT}
}
Note that I override only the settings that change in the PROD environment (some-other-setting
is thus the same as in DEV).
The config bootstrap code doesn't test anything
...
val conf = ConfigFactory.load()
...
To switch from the DEV to the PROD conf, simply pass a system property with the name of the config file to load:
java -Dconfig.resource=prod.conf ...
In DEV, no need to pass it since application.conf
will be loaded by default.
So here we're using Typesafe Config's default loading mechanism to achieve this.
I've created a simple project to demonstrate this technique. Feel free to clone and experiment.
Use typesafe Config. Create a Config object like this:
import com.typesafe.config._
object Config {
val env = if (System.getenv("SCALA_ENV") == null) "development" else System.getenv("SCALA_ENV")
val conf = ConfigFactory.load()
def apply() = conf.getConfig(env)
}
Then create the application.conf
file in src/main/resources
folder:
development {
your_app {
databaseUrl = "jdbc:mysql://localhost:3306/dev_db"
databaseUser = "xxxx"
databasePassword = "xxxx"
}
}
test {
your_app {
databaseUrl = "jdbc:mysql://localhost:3306/test_db"
databaseUser = "xxxxx"
databasePassword = "xxxx"
}
}
Now from anywhere in your application, you can access configuration:
Config().getString("your_app.databaseUrl")
If you have your environment set up (e.g. export SCALA_ENV=test
) when you run your application, it will consider the right configuration section. The default is development
I wasn't happy with how Daniel Cukiers solution did not allow defaults and overrides, so I changed it around to make full use of those.
The only configuration you have to do is set a ENVIRONMENT variable on the system (defaults to 'dev' if none is set)
(Java solution, compatible with Scala):
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class MyCompanyConfig {
public final static Config base = ConfigFactory.load().getConfig("mycompany");
public final static String environment = System.getenv("ENVIRONMENT") == null ? "dev" : System.getenv("ENVIRONMENT");
/**
* Returns a subtree of the base configuration with environment settings applied.
*
* @param setting The subtree to return config for.
* @return A config with base in given setting, with environment modifications applied.
*/
public static Config load(String setting) {
Config config = base.getConfig(setting);
if (config.hasPath(environment)) {
return config.getConfig(environment).withFallback(config);
}
return config;
}
}
This allows a single reference.conf in a library looking like this:
mycompany.module1 {
setting1 : "adefaultvalue"
url : "localhost"
test {
// will be used where ENVIRONMENT="test"
url : "test.mycompany.com"
}
prod {
// will be used where ENVIRONMENT="prod"
setting1 : "changethedefault"
url : "www.mycompany.com"
}
}
Usage:
Config conf = MyCompanyConfig.load("module1")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With