Configuration Files in Clojure

I recently made a contribution to ghijira, a small tool written in Clojure for exporting issues from GitHub in JIRA-compatible format. One of the problems to solve there was loading configuration from file.

Originally, it used have a separate config.clj file that looked like this:

(def auth "EMAIL:PASS")
(def ghuser "user-name")
(def ghproject "project-name")
(def user-map
  { "GithubUser1" "JIRAUser1"
    "GithubUser2" "JIRAUser2"})

Then it was imported in place with:

(load-file "config.clj")

I did not like it, because it did not feel very functional and the configuration file had too much noise (isn’t def form manipulation too much for a configuration file?).

For a moment I thought about using standard Java .properties files. They get the job done, but they’re also somewhat rigid and unwieldy.

It occurred to me I really could use something similar to Leiningen and its project.clj files: Make the config a plain Clojure map. It’s very flexible with minimal syntax, and it’s pure data just like it should be.

From a quick Google search I found the answer at StackOverflow.

It turns out I can rewrite my configuration file to:

{:auth      "EMAIL:PASS"
 :ghuser    "user-name"
 :ghproject "project-name"
 :user-map
   { "GithubUser1" "JIRAUser1"
     "GithubUser2" "JIRAUser2" }
}

And then load it in Clojure with read:

(defn load-config [filename]
  (with-open [r (io/reader filename)]
    (read (java.io.PushbackReader. r))))

That’s it, just call read.

I find this solution a lot more elegant and “pure”.

By the way, this data format is getting a life of its own, called Extensive Data Notation. The Relevance team has even published a library to use EDN in Ruby.

6 thoughts on “Configuration Files in Clojure

  1. And also, by doing do, you can guarantee the consistency of your configuration if you use binding to set the per-thread value of your conf for a given request.

  2. Just remember to (binding [*read-eval* false] (read …)), to only get data-structures. Otherwise you will execute the #=() magic, which may end badly if hostile third party edits your config file.

Leave a Reply

Your email address will not be published. Required fields are marked *

Spam protection by WP Captcha-Free