I have recently been working on a server-side app and I needed to externalise some configuration. I’m using Twitter’s REST API and I wanted my API access-token and secret to be kept outside of the code. There are two main reasons for doing this, firstly because they should be kept private as they identify my app and the secret is used to sign API requests and secondly, if I ever needed to change them, I would want to do so without touching the code.
Ideally, what I wanted was to supply a configuration file in the Java Property format to my application using a system property, load the file in code and then look-up property values by key. Whilst I could have come up with something myself, I really wanted to focus on writing the app.
After a bit of searching I settled on Typesafe’s Config project, a hidden gem which provided exactly what I needed.
Getting Config to do what I wanted was straight forward, the project is well documented and there are plenty of examples to learn from. I’m using SBT to build my project so initially I had to add the dependency to my build file:
libraryDependencies += "com.typesafe.config" % "config" % "0.3.0"
Next, to read an external property file, I needed to specify the system property
config.file pointing to the location of the configuration file that contained my properties. For me this meant appending a Java option to my SBT build file:
javaOptions += "-Dconfig.file=../deployment/twitter.properties"
I also needed to fork execution so the option was picked up when running my application in SBT:
Finally, in my code I needed to use the ConfigFactory to get a Config instance. This is then used to look up properties by key:
val conf = ConfigFactory.load()
val accessToken = conf.getString("accessToken")
val accessTokenSecret = conf.getString("accessTokenSecret")
Notice how the load call on
ConfigFactory requires no arguments, this is because Config has a resolution mechanism which first looks for known system properties before searching for a known resource on the classpath. Dead simple.
Apart from loading properties from the file system, Config allows you load from a URL, specify your configuration in JSON or HOCON - a more convient super-set of JSON and supports more complicated scenarios such as configuration inheritence and merging.
Relying on convention over configuration I found Config brilliantly simple to set up and use and urge you to take a look.