In Maven projects, we tend to use
.properties files to store various configurations, and use Maven profiles to switch between development and production environments. Like the following example:
As for Leiningen projects, there’s no variable substitution in profile facility, and although in profiles we could use
:resources to compact production-wise files into Jar, these files are actually replacing the original ones, instead of being merged. One solution is to strictly seperate environment specific configs from the others, so the replacement will be ok. But here I take another approach, to manually load files from difference locations, and then merge them.
Instead of using
.properties, we’ll use
.clj files directly, since it’s more expressive and Clojure makes it very easy to utilize them.
This function assumes the following directory layout:
database.cljs are like:
.clj files simply contains a
map object, and we use
read-string facility to parse the map. Since the latter map is merged into the former one, we can include some default settings without worrying about whether they’ll be available.
Here I use the word ‘outter’, which means those configs are related to environments, and will override the default settings. In this section, I’ll introduce some typical places to put these outter configs and how to use them.
First of all, this directory should be removed from version control, such as
And then, developers can put production or local configuration files in this directory.
In production, there’s typically a ‘compiling server’, which can be used to store production configs. After compiling, the Jar file will include the proper configs and are ready to be deployed.
We could simply replace the
override directory with an absolute path, such as
/home/www/config. The pros are that we don’t need to recompile the jar files when config changes, and some of the configs could be shared between different projects.
But in such approach, you’ll need a provisioning tool like Puppet to manage those configs and notify the applications to restart. For something like Hadoop MapReduce job, it’s probably not practical to have such a directory on every compute node.
Another thing I want to mention in this approach is that, I suggest using an environment variable to indicate the path to config directory, not hard-coded in application. As a matter of fact, you could even place all configs into env vars, as suggested by 12-factor apps.
As for really big corporations, a central configuration server is necessary. One popular option is to use ZooKeeper. Or your companies have some service-discovery mechanism. These are really advanced topics, and I’ll leave them to the readers.
Lastly, I’ll share a snippet that’ll manage the configs, it’s actually quite easy: